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

JavaScriptures 4.2 - Local State

JavaScriptures 4.2 - Local State

Artsy Open Source

April 12, 2018
Tweet

More Decks by Artsy Open Source

Other Decks in Programming

Transcript

  1. Local State
    The lesser state to rule the night
    JavaScriptures IV.II
    Eve and Chris

    View Slide

  2. State

    View Slide

  3. React has championed the concept of
    1-way data flow

    View Slide

  4. Data is passed into a component as
    props, and components then pass that
    data to other components as props

    View Slide

  5. When data is passed in it is immutable
    and cannot change

    View Slide

  6. View Slide

  7. If you can't change the data that’s
    passed into a component, how does one
    manage state?

    View Slide

  8. Via `setState()`

    View Slide

  9. View Slide

  10. setState can only be used in React class
    components, via `React.Component`

    View Slide

  11. View Slide

  12. View Slide

  13. Can modify state through calls to
    `setState`, for example on UI interactions

    View Slide

  14. View Slide

  15. UI interaction can be easily managed
    within a single class -- think, button
    toggles, show / hide, basic http list views

    View Slide

  16. View Slide

  17. This works well most of the time!

    View Slide

  18. `setState` can take you far, but problems
    begin to occur when complex UI
    interactions need to be managed across
    multiple components

    View Slide

  19. View Slide

  20. View Slide

  21. View Slide

  22. When component setState starts to
    manage App state and is scattered
    across a codebase it begins to feel
    suspiciously like MVC and becomes
    increasingly hard to scale

    View Slide

  23. A “predictable state container for JavaScript
    apps”

    View Slide


  24. It helps you write applications that
    behave consistently,
    run in different environments (client, server, and native),
    and are easy to test.

    https://redux.js.org/

    View Slide

  25. Not a framework,
    but an architecture for data-flow

    View Slide

  26. Not a framework,
    but an architecture for data-flow
    ● Based on Flux

    View Slide

  27. Not a framework,
    but an architecture for data-flow
    ● Based on Flux
    ● Implements a Unidirectional Data Flow

    View Slide

  28. View Slide

  29. Single source of truth
    “The state of your whole application is stored in an object tree within a single store.”
    What is Redux?

    View Slide

  30. State is read-only
    The only way to change the state is to emit an action, an object describing what happened.
    What is Redux?

    View Slide

  31. Changes are Made with
    Pure Functions
    To specify how the state tree is transformed by actions, you write pure reducers.
    What is Redux?

    View Slide

  32. Basic Redux Concepts

    View Slide

  33. Store
    ● A plain object, this is our one true source
    ● The provider of a universal state to your entire app

    View Slide




  34. View Slide

  35. Store
    ● A plain object, this is our one true source,
    ● The provider of a universal state to your entire app
    Actions
    ● Centralized set of functions for manipulating data in the store
    ● All actions return a plain object describing what happened

    View Slide

  36. export const changeAdminStatus = ({isAdmin}) => ({
    type: actions.CHANGE_ADMIN_STATUS,
    payload: { isAdmin }
    })
    export const actions = {
    CHANGE_ADMIN_STATUS: 'CHANGE_ADMIN_STATUS'
    }

    View Slide

  37. export const changeAdminStatus = ({isAdmin}) => ({
    type: actions.CHANGE_ADMIN_STATUS,
    payload: { isAdmin }
    })
    export const fetchUsers = () => {
    return async (getState) => {
    const users = await http.get(‘/users’)
    return {
    type: actions.FETCH_USERS,
    payload: { users }
    }
    }
    }
    export const actions = {
    CHANGE_ADMIN_STATUS: 'CHANGE_ADMIN_STATUS'
    FETCH_USERS: 'FETCH_USERS'
    }
    With the introduction of middleware...

    View Slide

  38. Store
    ● A plain object, this is our one true source,
    ● The provider of a universal state to your entire app
    Actions
    ● Centralized set of functions for manipulating data in the store
    ● All actions return a plain object describing what happened
    Reducers
    ● Called with two arguments from the store: the current state tree and an action
    ● Outlines the shape of an initial state

    View Slide

  39. export function appReducer (state = initialState, action) {
    switch (action.type) {
    case CHANGE_ADMIN_STATUS:
    return Object.assign({}, state, {
    isAdmin: action.payload.isAdmin
    })
    default:
    return state
    }
    }

    View Slide

  40. View Slide

  41. Dispatch
    ● The thread between the store/reducer/actions

    View Slide

  42. store.dispatch(someAction())

    View Slide

  43. Dispatch
    ● The thread connecting the store/reducer/actions
    Middleware
    ● Interrupt dispatched actions with libraries or your own functions

    View Slide

  44. Use Case
    Positron (aka Writer)

    View Slide

  45. View Slide

  46. Legacy Setup in Positron

    View Slide

  47. ● Backbone used for models

    View Slide

  48. ● Backbone used for models
    ● React components rendered inside Backbone parent views

    View Slide

  49. ● Backbone used for models
    ● React components rendered inside Backbone parent views
    ● Mixture of Backbone and React in UI components

    View Slide

  50. ● Backbone used for models
    ● React components rendered inside Backbone parent views
    ● Mixture of Backbone and React in UI components
    ● React components used Backbone’s set/get methods for all data mutations

    View Slide

  51. Pitfalls of Legacy Setup

    View Slide

  52. React and Backbone elements in same UI could have separate instances of shared data

    View Slide

  53. React and Backbone elements in same UI could have separate instances of shared data
    ● React and Backbone lifecycles exist independently from each other
    ● Listeners for Backbone ‘change’ events were scattered throughout app to trigger re-renders

    View Slide

  54. React and Backbone elements in same UI could have separate instances of shared data
    ● React and Backbone lifecycles exist independently from each other
    ● Listeners for Backbone ‘change’ events were scattered throughout app to trigger re-renders
    Props and onChange functions were passed down the entire component tree

    View Slide

  55. React and Backbone elements in same UI could have separate instances of shared data
    ● React and Backbone lifecycles exist independently from each other
    ● Listeners for Backbone ‘change’ events were scattered throughout app to trigger re-renders
    Props and onChange functions were passed down the entire component tree
    ● Bug fixing is hard when tracking through deep layers of nesting

    View Slide

  56. React and Backbone elements in same UI could have separate instances of shared data
    ● React and Backbone lifecycles exist independently from each other
    ● Listeners for Backbone ‘change’ events were scattered throughout app to trigger re-renders
    Props and onChange functions were passed down the entire component tree
    ● Bug fixing is hard when tracking through deep layers of nesting
    Data loss and views becoming out-of-sync is possible when components unmount

    View Slide

  57. React and Backbone elements in same UI could have separate instances of shared data
    ● React and Backbone lifecycles exist independently from each other
    ● Listeners for Backbone ‘change’ events were scattered throughout app to trigger re-renders
    Props and onChange functions were passed down the entire component tree
    ● Bug fixing is hard when tracking through deep layers of nesting
    Data loss and views becoming out-of-sync is possible when components unmount
    ● Rather than conditionally mounting components, we’d use jQuery to hide them

    View Slide

  58. View Slide

  59. Benefits of Moving to Redux

    View Slide

  60. One true source: Centralized data store is available to all components
    ● A consistent source for editable data
    ● But also can contain other information, like saved status or client errors

    View Slide

  61. View Slide

  62. One true source: Centralized data store is available to all components
    ● A consistent source for editable data
    ● But also can contain other information, like saved status or client errors
    Components that access centralized store re-render automatically when data changes
    ● This operation can be memoized for highly performant update cycles

    View Slide

  63. One true source: Centralized data store is available to all components
    ● A consistent source for editable data
    ● But also can contain other information, like saved status or client errors
    Components that access centralized store re-render automatically when data changes
    ● This operation can be memoized for highly performant update cycles
    Functions for mutating and saving data are consolidated to a centralized set of
    actions
    ● Makes it easy to jump into a new codebase and see what’s possible

    View Slide

  64. View Slide

  65. … and there’s more

    View Slide

  66. Minimize props that are passed down component tree
    ● By Connecting components, you can access the app’s store in them directly

    View Slide

  67. View Slide

  68. Minimize props that are passed down component tree
    ● By Connecting components, you can access the app’s store in them directly
    Ability to log and track all calls to Redux actions in the console

    View Slide

  69. View Slide

  70. Should I Be Using This?

    View Slide

  71. View Slide

  72. ● Managing state with setState has become overly complicated

    View Slide

  73. ● Managing state with setState has become overly complicated
    ● State is shared between components that don’t have a parent/child relationship

    View Slide

  74. ● Managing state with setState has become overly complicated
    ● State is shared between components that don’t have a parent/child relationship
    ● State changes are reflected outside the component where they are triggered,
    or are paired with asynchronous functions

    View Slide

  75. ● Managing state with setState has become overly complicated
    ● State is shared between components that don’t have a parent/child relationship
    ● State changes are reflected outside the component where they are triggered,
    or are paired with asynchronous functions
    ● Following how your state changes is opaque,
    and a step-through/undo history is necessary to understand it

    View Slide

  76. ● Managing state with setState has become overly complicated
    ● State is shared between components that don’t have a parent/child relationship
    ● State changes are reflected outside the component where they are triggered,
    or are paired with asynchronous functions
    ● Following how your state changes is opaque,
    and a step-through/undo history is necessary to understand it
    ● Props are passed down the component tree liberally,
    including through places they aren’t used

    View Slide

  77. Create predictable, trackable outcomes

    View Slide

  78. Debug complex systems with ease

    View Slide

  79. Facilitate clean, clear code

    View Slide