Slide 1

Slide 1 text

.PC9ͷ࿩ 2017/7/22 Yokohama North Meetup ˌ6 #yokohama_north bati (@bati11_ )

Slide 2

Slide 2 text

3FBDU/BUJWFͰΞϓϦ࡞ͬͨ

Slide 3

Slide 3 text

• 3FBDU/BUJWF • ࢖ͬͯΔϥΠϒϥϦ • XJYSFBDUOBUJWFOBWJHBUJPO SFBDUOBUJWF JOUFSBDUBCMF SFBDUOBUJWFDBMFOEBS SFBDU OBUJWFTWH FUD • ετΞͲ͏͠Α͏ʁ

Slide 4

Slide 4 text

• ετΞͲ͏͠Α͏ʁ • 8FCͷํͰ͸7VFKTͱ7VFY࢖ͬͯΔ • 3FEVY͸ͳΜ͔৮Γ৺஍͕͋Μ·Γͩͬͨ • .PC9ʹͨ͠ • 7VFYʹ৮Γ৺஍͕͍ۙɺؾ͕ͨ͠ • IUUQTNPCYKTPSH

Slide 5

Slide 5 text

.PC9ͷલʹ

Slide 6

Slide 6 text

// @flow import { autorun, observable, action, computed } from 'mobx'; type Task = { task: string, completed: boolean, assignee: ?string, } export default class TodoStore { @observable todos: Array = []; @observable pendingRequests: number = 0; constructor() { autorun(() => console.log(this.report)); } @computed get completedTodosCount(): number { return this.todos.filter(todo => todo.completed === true).length; } @computed get report(): string { if (this.todos.length === 0) { return ""; } else { return `Next todo: "${this.todos[0].task}". ` + `Progress: ${this.completedTodosCount}/${this.todos.length}`; } } @action addTodo(task: string): void { this.todos.push({task, completed: false, assignee: null}); } }

Slide 7

Slide 7 text

Α͘෼͔Βͳ͍ͷ͕͍Δ

Slide 8

Slide 8 text

// @flow import { autorun, observable, action, computed } from 'mobx'; type Task = { task: string, completed: boolean, assignee: ?string, } export default class TodoStore { @observable todos: Array = []; @observable pendingRequests: number = 0; constructor() { autorun(() => console.log(this.report)); } @computed get completedTodosCount(): number { return this.todos.filter(todo => todo.completed === true).length; } @computed get report(): string { if (this.todos.length === 0) { return ""; } else { return `Next todo: "${this.todos[0].task}". ` + `Progress: ${this.completedTodosCount}/${this.todos.length}`; } } @action addTodo(task: string): void { this.todos.push({task, completed: false, assignee: null}); } } アロー構文 IUUQTEFWFMPQFSNP[JMMBPSHKBEPDT8FC +BWB4DSJQU3FGFSFODFBSSPX@GVODUJPOT

Slide 9

Slide 9 text

// @flow import { autorun, observable, action, computed } from 'mobx'; type Task = { task: string, completed: boolean, assignee: ?string, } export default class TodoStore { @observable todos: Array = []; @observable pendingRequests: number = 0; constructor() { autorun(() => console.log(this.report)); } @computed get completedTodosCount(): number { return this.todos.filter(todo => todo.completed === true).length; } @computed get report(): string { if (this.todos.length === 0) { return ""; } else { return `Next todo: "${this.todos[0].task}". ` + `Progress: ${this.completedTodosCount}/${this.todos.length}`; } } @action addTodo(task: string): void { this.todos.push({task, completed: false, assignee: null}); } } クラス、コンストラクタ、メソッド IUUQTEFWFMPQFSNP[JMMBPSHKBEPDT8FC +BWB4DSJQU3FGFSFODF$MBTTFT

Slide 10

Slide 10 text

// @flow import { autorun, observable, action, computed } from 'mobx'; type Task = { task: string, completed: boolean, assignee: ?string, } export default class TodoStore { @observable todos: Array = []; @observable pendingRequests: number = 0; constructor() { autorun(() => console.log(this.report)); } @computed get completedTodosCount(): number { return this.todos.filter(todo => todo.completed === true).length; } @computed get report(): string { if (this.todos.length === 0) { return ""; } else { return `Next todo: "${this.todos[0].task}". ` + `Progress: ${this.completedTodosCount}/${this.todos.length}`; } } @action addTodo(task: string): void { this.todos.push({task, completed: false, assignee: null}); } } getter IUUQTCBCFMKTJPMFBSOFT FDNBTDSJQUGFBUVSFTNPEVMFT

Slide 11

Slide 11 text

// @flow import { autorun, observable, action, computed } from 'mobx'; type Task = { task: string, completed: boolean, assignee: ?string, } export default class TodoStore { @observable todos: Array = []; @observable pendingRequests: number = 0; constructor() { autorun(() => console.log(this.report)); } @computed get completedTodosCount(): number { return this.todos.filter(todo => todo.completed === true).length; } @computed get report(): string { if (this.todos.length === 0) { return ""; } else { return `Next todo: "${this.todos[0].task}". ` + `Progress: ${this.completedTodosCount}/${this.todos.length}`; } } @action addTodo(task: string): void { this.todos.push({task, completed: false, assignee: null}); } } プロパティの省略形 IUUQTEFWFMPQFSNP[JMMBPSHKBEPDT8FC +BWB4DSJQU3FGFSFODF0QFSBUPST0CKFDU@JOJUJBMJ[FS

Slide 12

Slide 12 text

// @flow import { autorun, observable, action, computed } from 'mobx'; type Task = { task: string, completed: boolean, assignee: ?string, } export default class TodoStore { @observable todos: Array = []; @observable pendingRequests: number = 0; constructor() { autorun(() => console.log(this.report)); } @computed get completedTodosCount(): number { return this.todos.filter(todo => todo.completed === true).length; } @computed get report(): string { if (this.todos.length === 0) { return ""; } else { return `Next todo: "${this.todos[0].task}". ` + `Progress: ${this.completedTodosCount}/${this.todos.length}`; } } @action addTodo(task: string): void { this.todos.push({task, completed: false, assignee: null}); } } テンプレート文字列 IUUQTCBCFMKTJPMFBSOFTFDNBTDSJQU GFBUVSFTUFNQMBUFTUSJOHT

Slide 13

Slide 13 text

// @flow import { autorun, observable, action, computed } from 'mobx'; type Task = { task: string, completed: boolean, assignee: ?string, } export default class TodoStore { @observable todos: Array = []; @observable pendingRequests: number = 0; constructor() { autorun(() => console.log(this.report)); } @computed get completedTodosCount(): number { return this.todos.filter(todo => todo.completed === true).length; } @computed get report(): string { if (this.todos.length === 0) { return ""; } else { return `Next todo: "${this.todos[0].task}". ` + `Progress: ${this.completedTodosCount}/${this.todos.length}`; } } @action addTodo(task: string): void { this.todos.push({task, completed: false, assignee: null}); } } モジュール(export, import) IUUQTCBCFMKTJPMFBSOFTFDNBTDSJQU GFBUVSFTNPEVMFT

Slide 14

Slide 14 text

// @flow import { autorun, observable, action, computed } from 'mobx'; type Task = { task: string, completed: boolean, assignee: ?string, } export default class TodoStore { @observable todos: Array = []; @observable pendingRequests: number = 0; constructor() { autorun(() => console.log(this.report)); } @computed get completedTodosCount(): number { return this.todos.filter(todo => todo.completed === true).length; } @computed get report(): string { if (this.todos.length === 0) { return ""; } else { return `Next todo: "${this.todos[0].task}". ` + `Progress: ${this.completedTodosCount}/${this.todos.length}`; } } @action addTodo(task: string): void { this.todos.push({task, completed: false, assignee: null}); } } クラスのプロパティ IUUQTHJUIVCDPNUDQSPQPTBMDMBTTQVCMJDpFMET

Slide 15

Slide 15 text

// @flow import { autorun, observable, action, computed } from 'mobx'; type Task = { task: string, completed: boolean, assignee: ?string, } export default class TodoStore { @observable todos: Array = []; @observable pendingRequests: number = 0; constructor() { autorun(() => console.log(this.report)); } @computed get completedTodosCount(): number { return this.todos.filter(todo => todo.completed === true).length; } @computed get report(): string { if (this.todos.length === 0) { return ""; } else { return `Next todo: "${this.todos[0].task}". ` + `Progress: ${this.completedTodosCount}/${this.todos.length}`; } } @action addTodo(task: string): void { this.todos.push({task, completed: false, assignee: null}); } } デコレータ IUUQTHJUIVCDPNUDQSPQPTBMEFDPSBUPST

Slide 16

Slide 16 text

// @flow import { autorun, observable, action, computed } from 'mobx'; type Task = { task: string, completed: boolean, assignee: ?string, } export default class TodoStore { @observable todos: Array = []; @observable pendingRequests: number = 0; constructor() { autorun(() => console.log(this.report)); } @computed get completedTodosCount(): number { return this.todos.filter(todo => todo.completed === true).length; } @computed get report(): string { if (this.todos.length === 0) { return ""; } else { return `Next todo: "${this.todos[0].task}". ` + `Progress: ${this.completedTodosCount}/${this.todos.length}`; } } @action addTodo(task: string): void { this.todos.push({task, completed: false, assignee: null}); } } Flow IUUQTqPXPSH

Slide 17

Slide 17 text

// @flow import { autorun, observable, action, computed } from 'mobx'; type Task = { task: string, completed: boolean, assignee: ?string, } export default class TodoStore { @observable todos: Array = []; @observable pendingRequests: number = 0; constructor() { autorun(() => console.log(this.report)); } @computed get completedTodosCount(): number { return this.todos.filter(todo => todo.completed === true).length; } @computed get report(): string { if (this.todos.length === 0) { return ""; } else { return `Next todo: "${this.todos[0].task}". ` + `Progress: ${this.completedTodosCount}/${this.todos.length}`; } } @action addTodo(task: string): void { this.todos.push({task, completed: false, assignee: null}); } }

Slide 18

Slide 18 text

.PC9Ͱ50%0ετΞ

Slide 19

Slide 19 text

• ಈ͔͠ͳ͕Βݟ͍͖ͯ·͠ΐ͏ʂ • ಈ͔͢લʹ

Slide 20

Slide 20 text

GMPXͳ͠Ͱ͍͖·͢

Slide 21

Slide 21 text

import { autorun, observable, action, computed } from 'mobx'; export default class TodoStore { @observable todos = []; @observable pendingRequests = 0; constructor() { autorun(() => console.log(this.report)); } @computed get completedTodosCount() { return this.todos.filter(todo => todo.completed === true).length; } @computed get report() { if (this.todos.length === 0) { return ""; } else { return `Next todo: "${this.todos[0].task}". ` + `Progress: ${this.completedTodosCount}/${this.todos.length}`; } } @action addTodo(task) { this.todos.push({task, completed: false, assignee: null}); } }

Slide 22

Slide 22 text

.PC9%FW5PPMTΛ ಋೖ͓͖ͯ͠·͢

Slide 23

Slide 23 text

• .PC9%FW5PPMT • IUUQTHJUIVCDPN[BMNPYJTVTNPCYSFNPUFEFW import { autorun, observable, action, computed } from 'mobx'; import remotedev from 'mobx-remotedev/lib/dev'; @remotedev export default class TodoStore { ・・・ }

Slide 24

Slide 24 text

ಈ͔ͯ͠Έ·͢

Slide 25

Slide 25 text

• ಈ͔͠ͳ͕Βݟ͍͖ͯ·͠ΐ͏ʂ • ಈ͔͢·Ͱͷखॱ͸ϒϩάʹॻ͖·ͨ͠ • IUUQCBUJCMPHIBUFOBCMPHDPNFOUSZ

Slide 26

Slide 26 text

• !PCTFSWBCMFͳϓϩύςΟΛมߋ͢Δͱɾɾɾ • BVUPSVOʹࢦఆͨ͠ॲཧ͕ࣗಈతʹ࣮ߦ͞ΕΔ export default class TodoStore { @observable todos = []; @observable pendingRequests = 0; constructor() { autorun(() => console.log(this.report)); } ・・・ @action addTodo(task) { this.todos.push({task, completed: false, assignee: null}); } }

Slide 27

Slide 27 text

• !BDUJPOͳϝιουͰ!PCTFSWBCMFͳϓϩύ ςΟΛมߋ͢Δ • VTF4USJDUΛ࢖͍ͬͯΔͱɺ!BDUJPOͳϝιο υҎ֎Ͱ!PCTFSWBCMFͳϓϩύςΟΛߋ৽ ͍ͯ͠ΔͱɺܯࠂΛग़ͯ͘͠ΕΔ • ݁Ռɺίʔυͷݟ௨͕͠ྑ͘ͳΔ

Slide 28

Slide 28 text

• !DPNQVUFEͳHFUUFSͷ݁Ռ͸Ωϟογϡ͞Ε Δ • DPOTPMFMPHΛॻ͍ͯࢼ͢ͱ෼͔Δ constructor() { autorun(() => console.log(this.report)); } @computed get report() { console.log("report"); if (this.todos.length === 0) { return ""; } else { return `Next todo: "${this.todos[0].task}". ` + `Progress: ${this.completedTodosCount}/${this.todos.length}`; } }

Slide 29

Slide 29 text

3FBDU%PN.PC9 Ͱ50%0ΞϓϦ

Slide 30

Slide 30 text

• NPCYSFBDU • IUUQTHJUIVCDPNNPCYKTNPCYSFBDU • !PCTFSWFS͕࢖͑ΔΑ͏ʹͳΔ • 3FBDUͷ$PNQPOFOUΫϥεʹ!PCTFSWFSΛ ͚ͭΔͱSFOEFSϝιου͕BVUPSVOͷର৅ʹ ͳΔ • ͭ·Γɺ!PCTFSWBCMFͳϓϩύςΟͷมߋ͕6* ʹ൓ө͞ΕΔʂ

Slide 31

Slide 31 text

• ಈ͔͠ͳ͕Βݟ͍͖ͯ·͠ΐ͏ʂ • ίʔυ͸ͪ͜Β • IUUQTHJTUHJUIVCDPN CBUJBC⒎FGGGDEBD

Slide 32

Slide 32 text

3FBDU/BUJWF.PC9

Slide 33

Slide 33 text

• 3FBDU/BUJWFͰ΋5PEP4UPSF͸ͦͷ··࢖͑Δ • 6*ͷ࡞Γํ͕%PN༻ͷ$PNQPOFOU͔ΒωΠςΟ ϒΞϓϦ༻ͷ$PNQPOFOUʹมΘΔ • ελΠϧ͸΍΍ࣅͯΔ

Slide 34

Slide 34 text

• ಈ͔͠ͳ͕Βݟ͍͖ͯ·͠ΐ͏ʂ • ίʔυ͸ͪ͜Β • IUUQTHJTUHJUIVCDPN CBUJEDGFFECC • 3FBDU/BUJWF%FCVHHFS • IUUQTHJUIVCDPNKIFOSFBDUOBUJWFEFCVHHFS

Slide 35

Slide 35 text

·ͱΊ

Slide 36

Slide 36 text

• .PC9ྑ͍ • .PC9ͷνϡʔτϦΞϧ • IUUQTNPCYKTPSHHFUUJOHTUBSUFEIUNM • ͨΊʹͳΔϒϩάهࣄ • IUUQMFBMPHIBUFCMPKQBSDIJWFDBUFHPSZ.PC9

Slide 37

Slide 37 text

• ָͰྑ͍ͷ͚ͩͲɺͦͷ൓໘ɺܾ·ͬͨϨʔϧ ͕ͳ͍ͷͰɺ࠷ॳʹઃܭͪΌΜͱ΍Βͳ͍ͱ࣮ ૷͢ΔਓʹΑͬͯɺ࣮૷ͷ࢓ํ͕όϥόϥʹͳΔ Մೳੑ͕ߴͦ͏ • ࣮ࡍͳΓ͔͚ͨ • ʂʂʂେࣄͳ͜ͱʂʂʂؾΛ͚ͭͳ͍ͱSFOEFS ͕Կճ΋࣮ߦ͞ΕΔɻˣಡΜͩํ͕ྑ͍ • IUUQTNPCYKTPSHCFTUSFBDUIUNM • IUUQTNPCYKTPSHSFGHVJEFNPEJpFSTIUNM