Upgrade to Pro — share decks privately, control downloads, hide ads and more …

MobX の話

06bfc3de5c1b439d2081b8a1f196afd7?s=47 bati11
July 22, 2017

MobX の話

06bfc3de5c1b439d2081b8a1f196afd7?s=128

bati11

July 22, 2017
Tweet

Transcript

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

  2. 3FBDU/BUJWFͰΞϓϦ࡞ͬͨ

  3. • 3FBDU/BUJWF • ࢖ͬͯΔϥΠϒϥϦ • XJYSFBDUOBUJWFOBWJHBUJPO SFBDUOBUJWF JOUFSBDUBCMF SFBDUOBUJWFDBMFOEBS SFBDU

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

    • IUUQTNPCYKTPSH
  5. .PC9ͷલʹ

  6. // @flow import { autorun, observable, action, computed } from

    'mobx'; type Task = { task: string, completed: boolean, assignee: ?string, } export default class TodoStore { @observable todos: Array<Task> = []; @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 "<none>"; } 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}); } }
  7. Α͘෼͔Βͳ͍ͷ͕͍Δ

  8. // @flow import { autorun, observable, action, computed } from

    'mobx'; type Task = { task: string, completed: boolean, assignee: ?string, } export default class TodoStore { @observable todos: Array<Task> = []; @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 "<none>"; } 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
  9. // @flow import { autorun, observable, action, computed } from

    'mobx'; type Task = { task: string, completed: boolean, assignee: ?string, } export default class TodoStore { @observable todos: Array<Task> = []; @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 "<none>"; } 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
  10. // @flow import { autorun, observable, action, computed } from

    'mobx'; type Task = { task: string, completed: boolean, assignee: ?string, } export default class TodoStore { @observable todos: Array<Task> = []; @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 "<none>"; } 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
  11. // @flow import { autorun, observable, action, computed } from

    'mobx'; type Task = { task: string, completed: boolean, assignee: ?string, } export default class TodoStore { @observable todos: Array<Task> = []; @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 "<none>"; } 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
  12. // @flow import { autorun, observable, action, computed } from

    'mobx'; type Task = { task: string, completed: boolean, assignee: ?string, } export default class TodoStore { @observable todos: Array<Task> = []; @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 "<none>"; } 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
  13. // @flow import { autorun, observable, action, computed } from

    'mobx'; type Task = { task: string, completed: boolean, assignee: ?string, } export default class TodoStore { @observable todos: Array<Task> = []; @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 "<none>"; } 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
  14. // @flow import { autorun, observable, action, computed } from

    'mobx'; type Task = { task: string, completed: boolean, assignee: ?string, } export default class TodoStore { @observable todos: Array<Task> = []; @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 "<none>"; } 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
  15. // @flow import { autorun, observable, action, computed } from

    'mobx'; type Task = { task: string, completed: boolean, assignee: ?string, } export default class TodoStore { @observable todos: Array<Task> = []; @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 "<none>"; } 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
  16. // @flow import { autorun, observable, action, computed } from

    'mobx'; type Task = { task: string, completed: boolean, assignee: ?string, } export default class TodoStore { @observable todos: Array<Task> = []; @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 "<none>"; } 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
  17. // @flow import { autorun, observable, action, computed } from

    'mobx'; type Task = { task: string, completed: boolean, assignee: ?string, } export default class TodoStore { @observable todos: Array<Task> = []; @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 "<none>"; } 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}); } }
  18. .PC9Ͱ50%0ετΞ

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

  20. GMPXͳ͠Ͱ͍͖·͢

  21. 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 "<none>"; } 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}); } }
  22. .PC9%FW5PPMTΛ ಋೖ͓͖ͯ͠·͢

  23. • .PC9%FW5PPMT • IUUQTHJUIVCDPN[BMNPYJTVTNPCYSFNPUFEFW import { autorun, observable, action, computed

    } from 'mobx'; import remotedev from 'mobx-remotedev/lib/dev'; @remotedev export default class TodoStore { ・・・ }
  24. ಈ͔ͯ͠Έ·͢

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

  26. • !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}); } }
  27. • !BDUJPOͳϝιουͰ!PCTFSWBCMFͳϓϩύ ςΟΛมߋ͢Δ • VTF4USJDUΛ࢖͍ͬͯΔͱɺ!BDUJPOͳϝιο υҎ֎Ͱ!PCTFSWBCMFͳϓϩύςΟΛߋ৽ ͍ͯ͠ΔͱɺܯࠂΛग़ͯ͘͠ΕΔ • ݁Ռɺίʔυͷݟ௨͕͠ྑ͘ͳΔ

  28. • !DPNQVUFEͳHFUUFSͷ݁Ռ͸Ωϟογϡ͞Ε Δ • DPOTPMFMPHΛॻ͍ͯࢼ͢ͱ෼͔Δ constructor() { autorun(() => console.log(this.report));

    } @computed get report() { console.log("report"); if (this.todos.length === 0) { return "<none>"; } else { return `Next todo: "${this.todos[0].task}". ` + `Progress: ${this.completedTodosCount}/${this.todos.length}`; } }
  29. 3FBDU%PN .PC9 Ͱ50%0ΞϓϦ

  30. • NPCYSFBDU • IUUQTHJUIVCDPNNPCYKTNPCYSFBDU • !PCTFSWFS͕࢖͑ΔΑ͏ʹͳΔ • 3FBDUͷ$PNQPOFOUΫϥεʹ!PCTFSWFSΛ ͚ͭΔͱSFOEFSϝιου͕BVUPSVOͷର৅ʹ ͳΔ

    • ͭ·Γɺ!PCTFSWBCMFͳϓϩύςΟͷมߋ͕6* ʹ൓ө͞ΕΔʂ
  31. • ಈ͔͠ͳ͕Βݟ͍͖ͯ·͠ΐ͏ʂ • ίʔυ͸ͪ͜Β • IUUQTHJTUHJUIVCDPN CBUJBC⒎FGGGDEBD

  32. 3FBDU/BUJWF .PC9

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

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

    IUUQTHJUIVCDPNKIFOSFBDUOBUJWFEFCVHHFS
  35. ·ͱΊ

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

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

    • IUUQTNPCYKTPSHCFTUSFBDUIUNM • IUUQTNPCYKTPSHSFGHVJEFNPEJpFSTIUNM