cookpad summer internship 2018 - JavaScript

cookpad summer internship 2018 - JavaScript

18b12f8f7910445b2637f0f21f59d467?s=128

Kazuhito Hokamura

September 18, 2018
Tweet

Transcript

  1. JavaScript クックパッド サマーインターンシップ 10 Day Tech for service engineers

  2. Agenda 1. JavaScript 2. TypeScript 3. React

  3. https://code.visualstudio.com/

  4. JavaScript

  5. JavaScript •ブラウザで動作するプログラミング言語 •HTMLを動的に変更してインタラクティブなWebサイト を構築するために使われる •最近はNode.jsやReactNativeなどブラウザ以外でも動 作する環境も多くある

  6. https://developer.mozilla.org/ja/

  7. Development/Debug

  8. 基本文法

  9. // جຊతʹ͸constΛ࢖͏ const str = 'x'; const arr = [1,

    2, 3]; // ఆٛޙʹ࠶୅ೖ͕ඞཁͳ৔߹͸letΛ࢖͏ let message; if (err) { message = 'error!';
 } else { message = 'ok!';
 } 変数宣言
  10. const num1 = 100; const num2 = 3.141592; const str1

    = 'xxx'; const str2 = "yyy"; const str3 = `foo${str}bar`; const x = null; const bool = true; const re = /foo.+$/i; リテラル
  11. const arr = [1, 2, 3]; arr[0] //=> 1 //

    for-ofͰΠςϨʔγϣϯ for (const v of arr) { console.log(v); // 1, 2, 3 } // ֤छϝιουͰΠςϨʔγϣϯ arr.forEach((v) => { console.log(v); }) //=> 1, 2, 3 arr.map((v) => { return v * 2; }); //=> [2, 4, 6] arr.filter((v) => { return v > 1; }); //=> [2, 3] 配列
  12. const obj = { foo: 'bar', fn: () => {

    console.log('hello!') } }; obj.foo; //=> 'bar' obj.fn(); //=> hello! obj.a = 'b'; // Shorthand property names const x = 1; const y = 2; const obj2 = { x, y }; // { x: x, y: y } オブジェクト
  13. // function จ function square(x) { return x * x;

    } // function ࣜ const square = function(x) { return x * x; }; // Arrow function ࣜ const square = (x) => { return x * x; }; // Ҿ਺͕1ͭͷͱ͖͸ () ΛলུՄೳɻ{ } Λলུͨ͠৔߹୯Ұͷ͕ࣜॻ͚ͯͦͷࣜͷ஋͕return͞ΕΔ const square = x => x * x; square(5); //=> 25 関数
  14. class Greeter { constructor(name) { this.name = name; } greet()

    { return `Hello ${this.name}!`; } } const g = new Greeter('hokaccha'); g.greet(); //=> 'Hello hokaccha!'; Class
  15. Modules // lib/Greeter.js export default class Greeter { constructor(name) {

    this.name = name; } greet() { return `Hello ${name}!`; } } export function hello(name) { return `Hello ${name}!`; }
  16. Modules // app.js // default import import Greeter from './lib/Greeter';

    // named import import { hello } from './lib/Greeter'; // mixed import Greeter, { hello } from './lib/Greeter';
  17. 非同期処理

  18. 同期 // Ծʹwait͕ॲཧΛϒϩοΫͨ͠ͱ͢Δͱ଴͍ͬͯΔؒʹԿ΋Ͱ͖ͳ͍ wait(1000); doSomething(); 非同期 // ଴͕ͪ࣌ؒܦաͨ͠Β࣮ߦ͞ΕΔؔ਺Λొ࿥ wait(1000, ()

    => { doSomething(); }); // ܧଓͯ͠ॲཧΛଓ͚ΒΕΔ
  19. 非同期処理の実装 •callback •Promise •async/await

  20. callback http.get('/a', response => { // ... });

  21. callback http.get('/a', responseA => { http.get('/b', responseB => { http.get('/c',

    responseC => { // ... }); }); });
  22. callback http.get('/a', (err, responseA) => { if (err) { return

    handleError(err); } http.get('/b', (err, responseB) => { if (err) { return handleError(err); } http.get('/c', (err, responseC) => { if (err) { return handleError(err); } // ... }); }); });
  23. Promise function get(url) { return new Promise((resolve, reject) => {

    http.get(url, (err, response) => { if (err) { reject(err); } else { resolve(response); } }); }); } get('/a').then(response => { // do something }).catch(err => { // error handling });
  24. Promise get('/a') .then(responseA => { return get('/b'); }) .then(responseB =>

    { return get('/c'); }) .then(responseC => { // do something }) .catch(err => { // error handling });
  25. async/await async function req() { const responseA = await get('/a');

    const responseB = await get('/b'); const responseC = await get('/c'); return responseC; } async function f() { try { const res = await req(); // do something } catch (err) { // error handling } }
  26. DOM

  27. DOM •HTML文書をプログラムから扱うためのAPI仕様 •JavaScriptの言語仕様とは別に仕様が策定されている

  28. <!DOCTYPE html> <html> <head> <script src="app.js" defer></script> </head> <body> <button

    id="button">Click Me!</button> <div id="message"></div> </body> </html>
  29. // HTMLʹॻ͔Ε͍ͯΔ button ཁૉΛऔಘ const button = document.getElementById('button'); // click͞Εͨͱ͖ͷϋϯυϥʔΛొ࿥

    button.addEventListener('click', async () => { // HTTP RequestͰAPIΛݺͼग़͢ const response = await fetch('/message'); const body = await response.json(); // #messageͷ಺༰Λॻ͖׵͑Δ document.getElementById('message').innerHTML = body.message; });
  30. // HTMLʹॻ͔Ε͍ͯΔ button ཁૉΛऔಘ const button = document.getElementById('button'); // click͞Εͨͱ͖ͷϋϯυϥʔΛొ࿥

    button.addEventListener('click', async () => { // HTTP RequestͰAPIΛݺͼग़͢ const response = await fetch('/message'); const body = await response.json(); // #messageͷ಺༰Λॻ͖׵͑Δ document.getElementById('message').innerHTML = body.message; }); %0."1*
  31. TypeScript

  32. TypeScript •Microsoftによって開発されているプログラミング言語 •JavaScriptに静的型付けの機能を取り入れたAltJS •JavaScriptのスーパーセット

  33. JavaScript function greeter(person) { return "Hello, " + person; }

    const user = "hokaccha"; const message = greeter(user);
  34. TypeScript function greeter(person: string): string { return "Hello, " +

    person; } const user = "hokaccha"; const message = greeter(user);
  35. TypeScript function greeter(person: string): string { return "Hello, " +

    person; } const user = [1, 2, 3]; const message = greeter(user); //=> error TS2345: Argument of type 'number[]' is not assignable to parameter of type 'string'.
  36. Basic Types let str: string; let num: number; let bool:

    boolean; let arr: string[]; let fn: (a: string, b: string) => boolean; type StrOrArr = string | string[]; type StrOrNull = string | null;
  37. Generics class Queue<T> { private data: T[] = []; enqueue(item:

    T) { return this.data.push(item); } dequeue(): T { return this.data.shift(); } } const queue = new Queue<number>(); queue.enqueue(10); queue.enqueue('x'); // Error!
  38. Generics interface User { name: string; } async function getUser():

    Promise<User> { const response = await fetch('/user'); const body = await response.json(); return body; } async function f() { const user: User = await getUser(); }
  39. Gradual Typing

  40. Gradual Typing •静的片付けを部分的に導入することができる型システム •TypeScriptでは型検査をしないany型により実現される

  41. // Ҿ਺ͷܕ͕anyʹͳΔͷͰͲΜͳܕͰ΋௨Δ function greeter(person) { return "Hello, " + person;

    } const user = [1, 2, 3]; const message = greeter(user); //=> ok Gradual Typing
  42. Structural Subtyping

  43. •部分型かどうかを構造が同じかどうかで判定する •静的型におけるダックタイピング Structural Subtyping

  44. interface Person { firstName: string; lastName: string; } class User

    { firstName: string; lastName: string; } const user1: Person = new User(); // ok const user2: Person = { firstName: "Kazuhito", lastName: "Hokamura" }; // ok Structural Subtyping
  45. class User { name: string; } class Product { name:

    string; } const user: User = new Product(); // ok const product: Product = new User(); // ok Structural Subtyping
  46. React

  47. JavaScript Frameworks •jQuery •Backbone.js •Angular •Vue.js •React

  48. None
  49. class App extends React.Component { constructor(props) { super(props); this.state =

    { name: '' }; } handleInput(event) { this.setState({ name: event.target.value }); } render() { return <div> <input type="text" onInput={event => this.handleInput(event)} /> <div>Hello, {this.state.name}</div> </div>; } } ReactDOM.render(<App />, document.getElementById('app'));
  50. class Button extends React.Component { render() { return <button onClick={()

    => this.props.onClick()}> <i className={`icon-${this.props.icon}`} /> {this.props.label} </button> } } <Button label="Click Me" icon="caret" onClick={() => alert('Hi!')} /> JSX
  51. None
  52. Lists and Keys class App extends React.Component { render() {

    // users: [{ id: 1, name: 'foo' }, { id: 2, name: 'bar' }] const items = this.props.users.map(user => { return <li key={user.id}>{user.name}</li>; }); return <div>{items}</div>; } }
  53. interface State { name: string; } interface Props { defaultName:

    string; } class App extends React.Component<Props, State> { constructor(props: Props) { super(props); this.state = { name: props.defaultName }; } handleClick() { this.setState({ a: 'b' }); // Error } } <App foo="bar" />; // Error With TypeScript
  54. 設計パターン

  55. stateとprops •state: コンポーネント自身が管理している状態 •props: 親コンポーネントから受け取る不変なパラメータ

  56. Presentational Component •データを元にどういうviewを構築するかだけに専念する •状態を持たないStatelessなコンポーネントとして作る •親コンポーネントからもらうpropsのみに依存する

  57. class Greeter extends React.Component<{}, {}> { render() { return <div

    className="greeter">Hello, {this.props.name}</div>; } } // ୯ͳΔؔ਺ͱͯ͠΋ఆٛͰ͖Δ function Greeter(props) { return <div className="greeter">Hello, {this.props.name}</div>; } Stateless Component
  58. Container Component •ツリーのルートでstateを持つコンポーネント •子のコンポーネントに状態を渡してツリーを構築する •イベントをハンドリングしてstateの更新をおこなう

  59. class App extends React.Component { constructor(props) { super(props); this.state =

    { name: '' }; } handleInput(event) { this.setState({ name: event.target.value }); } render() { return <div> <input type="text" onInput={event => this.handleInput(event)} /> <Greeter name={this.state.name} /> </div>; } } Container Component
  60. Container Component Stateless Component

  61. 1. イベント発生

  62. 1. イベント発生 2. 更新通知

  63. 1. イベント発生 2. 更新通知 3. state更新

  64. 1. イベント発生 2. 更新通知 3. state更新 4. DOM更新

  65. Lifecycle

  66. Component Lifecycle

  67. Fetch data class App extends React.Component { constructor(props) { super(props);

    this.state = { name: '' }; } async componentDidMount() { const response = await fetch('/user'); const body = await response.json(); this.setState({ name: body.name }); } render() { // ... } }
  68. Practice

  69. 1. Rubyのサーバーから書籍のリストを取得して表示 2. タイトルでインクリメンタルサーチする機能を実装 3. 各フィールドでソートできる機能を実装 4. スタイルをいい感じにする

  70. 環境構築 $ npm install -g create-react-app $ create-react-app booklist-front \

    --scripts-version=@hokaccha/create-react-app-ts-dev $ cd booklist-front $ yarn start