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

State is the source of all bugs

State is the source of all bugs

Learn what Redux is and how you can follow the redux architecture to scale and organize your applications.

Vince Speelman

April 14, 2018
Tweet

More Decks by Vince Speelman

Other Decks in Technology

Transcript

  1. 1
    State is the source
    of all bugs.

    View Slide

  2. 2

    View Slide

  3. 2

    View Slide

  4. 2
    Does this involve
    new libraries?

    View Slide

  5. 2
    Yes.
    Get Over It.

    View Slide

  6. 3
    New phone, who dis?

    View Slide

  7. 4

    View Slide

  8. 5

    View Slide

  9. 6

    View Slide

  10. 7

    View Slide

  11. 8

    View Slide

  12. 9

    View Slide

  13. 10

    View Slide

  14. 11
    @VinSpee

    View Slide

  15. 12
    typeof thisFont == ‘code’

    View Slide

  16. 13
    State is the source
    of all bugs.

    View Slide

  17. 14
    State is the source
    of all bugs. Pretty much.

    View Slide

  18. 15
    State is the source
    of all bugs. Pretty much.
    At least the weird ones
    that aren’t browser-
    related.

    View Slide

  19. 16

    View Slide

  20. 17
    Redux

    View Slide

  21. 18
    Redux

    View Slide

  22. 18
    Redux

    View Slide

  23. 19

    View Slide

  24. 20
    Redux

    View Slide

  25. 20
    Redux

    View Slide

  26. 21
    Redux

    View Slide

  27. 22
    lol georbascrib bye

    View Slide

  28. 22
    lol georbascrib bye

    View Slide

  29. 23
    • JavaScript — redux
    • .NET — redux.NET
    • Java — reductor
    • Swift — ReSwift
    • Objective-C — Reflow
    • PHP — php-redux
    • ruby — redux.rb

    View Slide

  30. 24
    Redux

    View Slide

  31. 25
    state
    {}

    View Slide

  32. 26
    state
    {}
    store

    View Slide

  33. 27
    state
    {} {}
    new state

    store

    View Slide

  34. 28
    state
    {} {}
    new state

    store
    re-poo-cer

    View Slide

  35. 29
    = state.yourProp = newValue;
    state
    re-poo-cer

    View Slide

  36. 30
    Mutable operations
    necessitate side-effects.

    View Slide

  37. 31
    state
    {}
    store
    {}
    new state

    View Slide

  38. 32
    =
    (state, { payload }) => ({
    ...state,
    yourProp: payload.newValue,
    });

    View Slide

  39. 33
    state
    {} {}
    new state

    store
    reducer

    View Slide

  40. 34
    state dispatcher action

    View Slide

  41. 35
    dispatcher
    dispatch({
    type: VIDEO.PLAY.REQUESTED,
    payload: videoPlayerInstance,
    });

    View Slide

  42. 36
    action
    type: VIDEO.PLAY.REQUESTED,
    type: VIDEO.PLAY.FULFILLED,
    type: VIDEO.PLAY.REJECTED,
    type: ROUTER.UPDATE_LOCATION,

    View Slide

  43. 37
    action
    (state, { type, payload }) => {
    switch (type) {
    case VIDEO.PLAY.REQUESTED:
    return {
    ...state,
    loading: true,
    };

    View Slide

  44. 38
    action
    import { union } from ‘tagmeme’;
    const VideoPlayer = union([‘Requested’, ‘Fulfilled’, ‘Rejected’]);
    (state, action) => VIDEO_PLAYER.match(
    action,
    {
    Requested: () => ({ ...state, loading: true }),
    Fulfilled: () => ({ ...state, loading: false, status: ‘PLAYING’ }),
    Rejected: (error) => ({ ...state, loading: false, error }),
    },
    );

    View Slide

  45. 39
    action
    (state, { type, payload }) => {
    switch (type) {
    case VIDEO.PLAY.REQUESTED:
    return {
    ...state,
    loading: true,
    };

    View Slide

  46. 40
    This is the beauty of
    Redux.

    View Slide

  47. 41
    State can only be
    updated as a result of an
    action.

    View Slide

  48. 42
    We have a record of
    actions.

    View Slide

  49. 43

    View Slide

  50. 44
    How do I connect it to my
    UI?

    View Slide

  51. 45
    ui
    const VideoPlayer = ({ status, onPlay, onPause }) => (

    {status !== ‘PLAYING’ ? (
    play
    ) : (
    pause
    )}


    );

    View Slide

  52. 46
    ui
    connect(state => ({
    status: state.status,
    }), dispatch => ({
    onPlay: () => dispatch(VIDEO.PLAY.REQUESTED),
    onPause: () => dispatch(VIDEO.PAUSE.REQUESTED),
    })(VideoPlayer),

    View Slide

  53. 47
    Couldn’t my state tree get
    a bit messy?

    View Slide

  54. 48
    Couldn’t my state tree get
    a bit messy?
    YES.

    View Slide

  55. 49
    Tips

    View Slide

  56. 50
    1. Normalize your data.

    View Slide

  57. 51
    {
    users: [
    {
    id: 1,
    name: ‘Sam Hanes’,
    email: ‘[email protected]',
    },
    ],
    },

    View Slide

  58. 52
    {
    users: {
    entities: [
    1: {
    id: 1,
    name: ‘Sam Hanes’,
    email: ‘[email protected]',
    },
    ],
    result: [1],
    },
    },

    View Slide

  59. 53
    const entify = d =>
    d.reduce((a,c) => ({
    ...a,
    entities: {
    ...a.entities,
    [c.id]:c,
    },
    result: [...a.result, c.id],
    }),{});

    View Slide

  60. 54
    2. Don’t use booleans for
    everything.
    videoPlayer: {
    isPlaying: false,
    }

    View Slide

  61. 55
    videoPlayer: {
    isPlaying: false,
    isPaused: true,
    isLoaded: true,
    }
    2. Don’t use booleans for
    everything.

    View Slide

  62. 56
    videoPlayer: {
    status: ‘PLAYING’,
    loading: ‘COMPLETE’
    }
    2. Don’t use booleans for
    everything.

    View Slide

  63. 57
    3. Push outside concerns
    into middleware.

    View Slide

  64. 58
    3. Push outside concerns
    into middleware.
    wait, wtf is middleware?

    View Slide

  65. 59
    middleware
    Middleware are “action
    interceptors” that can
    execute side effects.

    View Slide

  66. 60
    middleware
    - Analytics

    View Slide

  67. 61
    middleware
    - Analytics
    -
    API calls

    View Slide

  68. 62
    middleware
    - Analytics
    -
    API calls
    -
    Legacy Systems

    View Slide

  69. 63
    login
    press
    dispatch
    login
    auth
    middleware

    View Slide

  70. 64
    auth middleware
    const authMiddleware = store => next => action => {
    if (action.type === 'LOGIN') {
    return legacy.login(action.payload).then(res =>
    next({
    ...action,
    payload: res,
    })
    );
    }
    return next(action);
    }

    View Slide

  71. 65
    3. Push outside concerns
    into middleware.

    View Slide

  72. 66
    4. Use selectors
    state => ({
    status: select.getPlayerStatus(state),
    })

    View Slide

  73. 67
    5. Use constants to name
    actions and use action
    creators

    View Slide

  74. 68
    6. Put everything in your
    global state tree.

    View Slide

  75. 69
    Redux

    View Slide

  76. 70
    • JavaScript — redux
    • .NET — redux.NET
    • Java — reductor
    • Swift — ReSwift
    • Objective-C — Reflow
    • PHP — php-redux
    • ruby — redux.rb

    View Slide

  77. 71
    @VinSpee

    View Slide