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

MobX の話

bati11
July 22, 2017

MobX の話

bati11

July 22, 2017
Tweet

More Decks by bati11

Other Decks in Programming

Transcript

  1. .PC9ͷ࿩
    2017/7/22 Yokohama North Meetup ˌ6

    #yokohama_north

    bati (@bati11_ )

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  5. .PC9ͷલʹ

    View Slide

  6. // @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});
    }
    }

    View Slide

  7. Α͘෼͔Βͳ͍ͷ͕͍Δ

    View Slide

  8. // @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
    [email protected]

    View Slide

  9. // @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

    View Slide

  10. // @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

    View Slide

  11. // @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
    [email protected][FS

    View Slide

  12. // @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

    View Slide

  13. // @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

    View Slide

  14. // @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

    View Slide

  15. // @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

    View Slide

  16. // @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

    View Slide

  17. // @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});
    }
    }

    View Slide

  18. .PC9Ͱ50%0ετΞ

    View Slide

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

    View Slide

  20. GMPXͳ͠Ͱ͍͖·͢

    View Slide

  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 "";
    } 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});
    }
    }

    View Slide

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

    View Slide

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

    View Slide

  24. ಈ͔ͯ͠Έ·͢

    View Slide

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

    View Slide

  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});
    }
    }

    View Slide

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

    View Slide

  28. • !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}`;
    }
    }

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  32. 3FBDU/BUJWF.PC9

    View Slide

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

    View Slide

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

    View Slide

  35. ·ͱΊ

    View Slide

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

    View Slide

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

    View Slide