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

The state of the state: React state management ...

The state of the state: React state management inย 2019

There's always been a large variety of ways to manage state in React. Redux has always been a popular choice, but with React 16, and recently released libraries, there are now even more options. What are these options, and why would you use any of these over any others?

Let's go through some popular choices for managing state in React and check their pros and cons and how opting in for each of these may help (or not) to scale your data flow.

Matheus Albuquerque

April 25, 2019
Tweet

More Decks by Matheus Albuquerque

Other Decks in Programming

Transcript

  1. """

  2. Apollo link state Unstated Stockroom alfa MOBX setState() Redux CONTEXT

    HOOKS reworm Relay React Automata freactal REDUX-ACT IMMER
  3. Apollo link state Unstated Stockroom alfa MOBX setState() Redux CONTEXT

    HOOKS reworm Relay React Automata freactal IMMER REDUX-ACT
  4. Apollo link state Unstated Stockroom alfa MOBX setState() Redux CONTEXT

    HOOKS reworm Relay React Automata freactal IMMER REDUX-ACT
  5. Apollo link state Unstated Stockroom alfa MOBX setState() Redux CONTEXT

    HOOKS reworm Relay React Automata freactal IMMER REDUX-ACT
  6. FEATURING: โ† A list of states โ† One initial state

    โ† A list of events that trigger transitions
  7. HIGHLIGHTS: โ† Preciseness of specs โ† Correctness of code โ†

    Less unimportant state / Less if clauses โ† Leverage knowledge from non-coders too
  8. CONS: โ† Surely an overkill for super simple components โ†

    Lack of familiarity from developers and designers โ† Small ecosystem
  9. Apollo link state Unstated Stockroom alfa MOBX setState() Redux CONTEXT

    HOOKS reworm Relay React Automata freactal IMMER REDUX-ACT
  10. Key Concepts: โ† DEFAULTS: Your base state. What you start

    with. โ† RESOLVERS: Where all the magic happens to retrieve and update your local data in the Apollo cache.
  11. HIGHLIGHTS: โ† Getting Apollo set up just for state management

    can be a bit of work โ† A natural way of querying and mutating state
  12. Apollo link state Unstated Stockroom alfa MOBX setState() Redux CONTEXT

    HOOKS reworm Relay React Automata freactal IMMER REDUX-ACT
  13. import React from 'react' import { Provider, create } from

    'reworm' const { set, get } = create({ name: 'John' }) class App extends React.Component { componentDidMount() { set(prev $% ({ name: 'Peter' + prev.name })) } render() { return ( <Provider> <div>{get(s $% s.name)}</div> </Provider> ) } }
  14. Apollo link state Unstated Stockroom alfa MOBX setState() Redux CONTEXT

    HOOKS reworm Relay React Automata freactal IMMER REDUX-ACT
  15. Key Concepts: โ† CONTEXT: Provides a way to pass data

    through the component tree without having to pass props down manually at every level. โ† HOOKS: Let you use state and other React features without writing a class
  16. Split contexts that don't change together function Button() { let

    theme = useContext(ThemeContext); &' The rest of your rendering logic return <ExpensiveTree className={theme} />; }
  17. Split your component in two, put memo in between function

    Button() { let appContextValue = useContext(AppContext); let theme = appContextValue.theme; &' Your "selector" return <ThemedButton theme={theme} /> } const ThemedButton = memo(({ theme }) $% { &' The rest of your rendering logic return <ExpensiveTree className={theme} />; });
  18. One component with useMemo inside function Button() { let appContextValue

    = useContext(AppContext); let theme = appContextValue.theme; &' Your "selector" return useMemo(() $% { &' The rest of your rendering logic return <ExpensiveTree className={theme} />; }, [theme]) }
  19. Apollo link state Unstated Stockroom alfa MOBX setState() Redux CONTEXT

    HOOKS reworm Relay React Automata freactal IMMER REDUX-ACT
  20. const loading = createReducer({}, initialState.loading) .on(actions.fetch, () $% true) .on(actions.setQuery,

    () $% true) const ids = createReducer({}, initialState.ids) .on(actions.setIds, (state, payload) $% [&&.payload]) .on(actions.delete, (state, payload) $% { return [&&.state.filter((id) $% id ))* payload)]; });
  21. Apollo link state Unstated Stockroom alfa MOBX setState() Redux CONTEXT

    HOOKS reworm Relay React Automata freactal IMMER REDUX-ACT
  22. WHY: โ† - Breakable โ† + Debuggable โ† + Performant

    Full Reconciliation REACT Reconciliation REACT + IMMUTABLE
  23. WHY: โ† - Breakable โ† + Debuggable โ† + Performant

    Full Reconciliation O(N^3) REACT Reconciliation O(N) REACT + IMMUTABLE O(LOGN)
  24. import update from "i!"utability-helper" const reducer = (state, action) $%

    { switch (action.type) { case ADD_TAG: return update(state, { [action.id]: { tags: { $push: [action.tag] } } }) default: return state } }
  25. const map1 = { foo: 1, bar: 2 } const

    map2 = I!"utable.Map(map1) const { foo, bar } = map2 console.log(foo) &' undefined console.log(bar) &' undefined
  26. const map1 = { foo: 1, bar: 2 } const

    map2 = produce(map1, draft $% { draft.foo += 10 }) const { foo, bar } = map2 console.log(foo) &' 11 console.log(map1.bar ++, bar) &' true
  27. exposes a single default function that does all the work

    const map1 = { foo: 1, bar: 2 } const map2 = produce(map1, draft $% { draft.foo += 10 }) const { foo, bar } = map2 console.log(foo) &' 11 console.log(map1.bar ++, bar) &' true
  28. const map1 = { foo: 1, bar: 2 } const

    map2 = produce(map1, draft $% { draft.foo += 10 }) const { foo, bar } = map2 console.log(foo) &' 11 console.log(map1.bar ++, bar) &' true apply all your changes to a temporarily draft State, which is a proxy of the currentState.
  29. your objects and arrays are really JavaScript objects and arrays,

    so you can do everything you would normally do const map1 = { foo: 1, bar: 2 } const map2 = produce(map1, draft $% { draft.foo += 10 }) const { foo, bar } = map2 console.log(foo) &' 11 console.log(map1.bar ++, bar) &' true
  30. &' add a tag to a todo { &&.state, [action.id]:

    { &&.state[action.id], tags: [ &&.state[action.id].tags, action.tag ] } } &' add a tag to a todo state[action.id].tags.push(action.tag)