$30 off During Our Annual Pro Sale. View Details »

Redux Middleware Wars (Japanese)

Redux Middleware Wars (Japanese)

M3 Tech meetup! #2 ~フロントエンドの副作用~
http://m3-engineer.connpass.com/event/33802/

Shuhei Kagawa

July 14, 2016
Tweet

More Decks by Shuhei Kagawa

Other Decks in Technology

Transcript

  1. Redux
    Middleware Wars

    View Slide

  2. Me
    • So$ware Engineer at M3, Inc.
    • ҩྍݱ৔Ͱ࢖͏γεςϜͷ։ൃ
    • AngularJS, Rails, Node.js, Babel, etc.
    • GitHub, Qiita: @shuhei
    • TwiGer: @shuheikagawa
    • ! Ϗʔϧݕఆ 2 ڃ

    View Slide

  3. Middleware ʹ͍ͭͯ࿩ͦ͢ͷલʹɾɾɾ

    View Slide

  4. ͦ΋ͦ΋ Redux ͱ͸ʁ
    • Predictable state container for JavaScript apps
    • ༧ଌՄೳͳঢ়ଶίϯςφʢ௚༁ʣ
    • ΋ͱ΋ͱ͸ Time traveling, hot reloading Λ໨తͱͯ͠࡞ΒΕͨ
    Flux తͳԿ͔

    View Slide

  5. Redux ͷ 3 ݪଇ
    1. ΞϓϦͷશঢ়ଶΛҰͭͷ Object
    (State) ͱͯ͠อ࣋
    2. Action ΛૹΔʢdispatchʣ͜ͱʹ
    ΑͬͯͷΈ State ΛมߋͰ͖Δʢͱ͍
    ͏͔৽͍͠ State ͕࡞ΒΕΔʣ
    3. Reducer ͱ͍͏ pure ͳؔ਺ʢಉ͡Ҿ
    ਺ʹରͯ͠ৗʹಉ͡ฦΓ஋Λฦ͢ʣʹ
    ΑͬͯͷΈঢ়ଶ͕มߋ͞ΕΔ
    reducer : (State, Action) -> State

    View Slide

  6. ! Pure ͳؔ਺ͱ͸ʁ
    • Ҿ਺ͷΈʹΑͬͯฦΓ஋͕ܾ·Δ
    • ؔ਺ͷ֎ͷঢ়ଶΛมߋ͠ͳ͍ʢ෭࡞༻͕ͳ͍ʣ

    View Slide

  7. ! Pure ͡Όͳ͍ؔ਺
    • ࣌ʹΑͬͯฦ͢஋͕ҧ͏
    • ฦΓ஋͕ͳ͍
    • Ҿ਺Λมߋͯ͠͠·͏
    • ޙͰίʔϧόοΫ͕ݺ͹ΕΔ
    • etc.

    View Slide

  8. ஌Β͵ؒʹΞϓϦ
    ͷঢ়ଶ͕มΘΔ͜
    ͱ͕ͳ͍

    View Slide

  9. View Slide

  10. ͱ͸͍͑ɺ෭࡞༻͸Ͳ͏͢Δͷʁ
    • AJAX
    • local storage
    • cookie
    • ϩά
    • etc.

    View Slide

  11. • Reducer ͷதʹॻ͘: ແཧ
    • View Component ͷதʹॻ͘: ͔ͤͬ͘ঢ়ଶΛ௥͍ग़ͨ͠ͷ
    ʹɾɾɾ
    • Ac4on Creator ͷதʹॻ͘: dispatch Λ౉͢ඞཁ͋Γ

    View Slide

  12. Middleware

    View Slide

  13. Redux Middleware ͱ͸
    • dispatch ͷલޙʹॲཧΛڬΉ
    • Action Λड͚ͯɺΰχϣΰχϣͰ͖
    Δ
    • Action Λͪΐͬͱ஗ΒͤͯૹΔ
    • ผͷ Action ʹஔ͖׵͑Δ
    • ඇಉظॲཧΛߦ͍ɺ݁ՌΛ Action
    ͱͯ͠ૹΔ
    • e.g. WSGI, Rack, Express, Koa, etc.

    View Slide

  14. ྫ: ͳʹ΋͠ͳ͍
    ड͚औͬͨ Ac$on Λͦͷ··࣍ͷ middleware ʹ౤͛Δ
    const passthrough = store => next => action => {
    return next(action);
    };

    View Slide

  15. ྫ: ϩάΛग़ྗ
    ࣍ͷ middleware ʹ ac+on Λ౤͛ΔʢnextʣલޙͰϩάΛग़ྗ
    const logger = store => next => action => {
    console.log('prev state', store.getState());
    console.log('action', action);
    const returnValue = next(action);
    console.log('next state', store.getState());
    return returnValue;
    };

    View Slide

  16. ྫ: Promise ͷ݁ՌΛ଴ͭ
    const promise = store => next => action => {
    if (typeof action.then === 'function') {
    return action.then(store.dispatch);
    } else {
    return next(action);
    }
    };
    function fetchPosts() {
    return fetch('/posts').then(res => res.json())
    .then(posts => ({ type: 'POSTS_FETCHED', posts }));
    }
    dispatch(fetchPosts);

    View Slide

  17. ࠓճ͸ඇಉظॲཧΛߦ͏ Middleware ʹয఺

    View Slide

  18. ΄͍͠΋ͷ
    • ! ςετͷ͠΍͢͞ʢϞοΫແ͠ͰςετͰ͖Δͱ࠷ߴʣ
    • " ۭ࣌Λ௒͑Δʢthro'ling, debouncingʣ
    • # ϩδοΫͷڽू౓
    • ✨ ։ൃͷ׆ൃ͞

    View Slide

  19. ඇಉظॲཧΛߦ͏ Middleware
    ಠஅͱภݟʹΑΓ...
    | ----------------- | ---- | --------- | ---- | ---- | ---- | ---- |
    | name | star | from | test | time | cohe | acti |
    | ----------------- | ---- | --------- | ---- | ---- | ---- | ---- |
    | redux-thunk | 2392 | '15/07/13 | C | C | B | A |
    | redux-promise | 864 | '15/07/02 | - | C | C | C |
    | redux-saga | 3172 | '15/11/30 | B | A | A | A |
    | redux-loop | 641 | '16/01/06 | A | C | B | C |
    | redux-observable | 634 | '16/02/16 | C | A | B | A |
    | ----------------- | ---- | --------- | ---- | ---- | ---- | ---- |
    ⭐ ͷ਺͸ 2016/7/5 ௐ΂

    View Slide

  20. redux-thunk ⭐2392
    Ac#on ͱͯؔ͠਺ʢthunkʣ͕དྷͨΒɺͦΕΛ࣮ߦ͢ΔʢҾ਺ʹ
    dispatch ͱ getStateʣ
    const fetchBeers = () => (dispatch, getState) => {
    return fetch('/beers')
    .then(res => res.json())
    .then(items => dispatch('FETCH_BEERS_SUCCEEDED', items))
    .catch(error => dispatch('FETCH_BEERS_FAILED', error));
    };
    dispatch(fetchBeers());

    View Slide

  21. redux-thunk ⭐2392
    • ! ϞοΫ͠ͳ͍ͱςετ͕ॻ͚ͳ͍
    • " Ac%on ΛҰ͔ͭͮͭ͠ड͚ΒΕͳ͍ͷͰɺdebounce ͳͲ͕
    ೉͍͠
    • # ΄Ͳ΄ͲʹෳࡶͳϩδοΫ͸ॻ͚Δ
    • ✨ ΄Ͳ΄Ͳʹϝϯς͞Ε͍ͯΔɻͦ΋ͦ΋ 13 ߦ͔͠ͳ͍
    • ࢀߟ: How to dispatch a Redux ac%on with a %meout?

    View Slide

  22. redux-promise ⭐864
    FSA (Flux Standard Ac/on) ͷ payload ͷ promise Λղܾ͠ɺ
    Ac/on ͱͯ͠ૹΓ௚ͯ͘͠ΕΔ
    function fetchItems() {
    const promise = fetch('/items').then(res => res.json());
    return {
    type: 'FETCH_ITEMS',
    payload: promise
    };
    }
    dispatch(fetchItems());

    View Slide

  23. redux-promise ⭐864
    • ! γϯϓϧͳͷͰɺͦ͜·Ͱςετ͠ͳͯ͘ྑͦ͞͏
    • " debounce ͳͲ΋Ͱ͖ͳ͍
    • # ෳࡶͳϩδοΫ͸ॻ͚ͳ͍
    • ✨ 4 ϲ݄ఔϝϯς͞Εͯͳ͍ɻ25 ߦ͚͕ͩͩɾɾɾ
    • Τϥʔॲཧͷൺֱతॏཁͦ͏ͳ MR ͕Ϛʔδ͞Ε͕ͨϦϦʔ
    ε͞Ε͍ͯͳ͍

    View Slide

  24. redux-saga ⭐3172
    Saga ͱݺ͹ΕΔ generator (saga) Ͱ෭࡞༻Λ൐͏ॲཧΛهड़
    function* fetchBeer(action) {
    try {
    const beers = yield call(fetchBeer, action.id);
    yield put({ type: 'FETCH_BEER_SUCCEEDED',
    payload: beers });
    } catch (error) {
    yield put({ type: 'FETCH_BEER_FAILED', error });
    }
    }
    function* watchFetchBeer() {
    yield* takeEvery('FETCH_BEER', fetchBeer);
    }

    View Slide

  25. redux-saga ⭐3172
    • ! ςετ͕͠΍͍͢ʂʂʂ
    • ෭࡞༻ϦΫΤετΛ yield ͯ͠ɺmiddleware ʹ࣮ߦͯ͠΋
    Β͍ɺ݁ՌΛड͚औΔ
    • ࣗ෼͸ pure ͳ··ෳࡶͳඇಉظॲཧ͕ॻ͚Δ
    • ৄ͘͠͸ @kuy ͞Μͷ͓࿩Ͱɾɾɾ

    View Slide

  26. redux-loop (store enhancer) ⭐641
    Elm Λਅࣅͨ APIɻreducer ͕ state ͚ͩͰͳ͘ Effects ΋ฦ͢
    function beers(state = [], action) {
    switch (action.type) {
    case 'FETCH_BEERS':
    return loop(state, Effects.promise(fetchBeers));
    case 'FETCH_BEERS_SUCCEEDED':
    return action.payload;
    default:
    return state;
    }
    }

    View Slide

  27. redux-loop (store enhancer) ⭐641
    • ! ϞοΫͳ͠ͰςετͰ͖Δ
    • Effects ͸ͨͩͷ Objectɻ࣮ߦ͢Δ·Ͱ෭࡞༻͸ى͖ͳ͍
    • " debounce ͳͲ͸Ͱ͖ͳͦ͞͏
    • # Effects Λ૊Έ߹ΘͤΔ͜ͱ͕Ͱ͖Δ
    • ✨ 3 ϲ݄΄Ͳϝϯς͞Ε͍ͯͳ͍ɻ࡞ऀ͕ Elm ͔͠ॻ͔ͳ͘
    ͳͬͯ͠·ͬͨʁ

    View Slide

  28. redux-observable ⭐ 634
    reducer ͷޙͰ Action Λड͚ͯ Action Λग़ྗ͢Δ Observable
    Λฦ͢
    function beerEpic(action$, store) {
    const beers$ = action$.ofType('FETCH_ITEMS')
    .mergeMap(() => Observable.fromPromise(fetchBeers()))
    .map(beers => ({ type: 'FETCH_BEERS_SUCCEEDED', payload: beers }));
    return Observable.merge(
    beers$,
    something$
    );
    }

    View Slide

  29. redux-observable ⭐ 634
    • ! ϞοΫ͠ͳ͍ͱςετͰ͖ͳ͍
    • " Rx ͷڧྗͳ operator Ͱ༰қʹۭ࣌Λ੍ͤΔ
    • # redux-saga తͳ background processor style ʹਐԽ
    • ෳࡶͳॲཧ΋ॻ͚Δ
    • ✨ ݱࡏ΋։ൃதɻͱͯ΋γϯϓϧ
    • Rx ͸ΩϚΔͱؾ͍͍࣋ͪʢݸਓͷײ૝ʣ

    View Slide

  30. τϨϯυʢʁʣ
    • σʔλͱͯ͠ͷ෭࡞༻ʢsaga, loop, Cycle.jsʣ
    • ෭࡞༻ϦΫΤετΛ middleware ͕ॲཧ͢Δ
    • ։ൃऀ͕ॻ͘ϩδοΫ͕៉ྷʹอͯΔ
    • Background processor ελΠϧʢsaga, observable, chooʣ
    • reducer ͷલͰ͸ͳ͘ޙͰ Action Λड͚Δ

    View Slide

  31. ࠙਌ձͰ͍Ζ͍Ζڭ͑ͯԼ͍͞ʂ

    View Slide

  32. Thanks!

    View Slide

  33. Credits
    • Chart of Redux from h0p:/
    /www.bebe0erdeveloper.com/coding/
    ge=ng-started-react-redux.html

    View Slide