setState ftw

setState ftw

"Nobody knows how to do anything without Redux anymore. It's ridiculous." - @mjackson
Let's fix it!

414db81dca21f468b4d7acd88172370c?s=128

Michele Bertoli

October 06, 2017
Tweet

Transcript

  1. setState ftw @MicheleBertoli

  2. My name’s Michele and I’m a React fanboy since 2014

  3. I work in Ads at Facebook, and I contribute to

    a pretty sophisticated React UI
  4. setState is the primary method you use to update the

    UI in React
  5. Are we really going to talk about setState for 40

    minutes?
  6. YES

  7. Ok, why?

  8. “I’m learning React but I don’t understand reducers.” Anonymous, Mar

    2017
  9. react

  10. react-redux redux react react-router react-router-redux

  11. react-redux redux react react-router react-router-redux

  12. The community

  13. “Nobody knows how to do anything without Redux anymore. It's

    ridiculous.” @mjackson, Jun 2016
  14. “3 Reasons why I stopped using React.setState.” @mweststrate, Jun 2016

  15. “I love setState. In 3 1/2 years, I haven't needed

    anything more.” @chantastic, Mar 2017
  16. “You might not need Redux.” @dan_abramov, Sep 2016

  17. Common Pitfalls

  18. setState({ title: 'Here comes the sun' }) console.log(this.state.title)

  19. setState is asynchronous

  20. setState({ counter: this.state.counter + 1 }) setState({ counter: this.state.counter +

    1 })
  21. Object.assign( prevState, { counter: this.state.counter + 1 }, { counter:

    this.state.counter + 1 }, )
  22. Multiple setState calls get batched

  23. this.state.title = 'Come together'

  24. Mutating the state is an anti-pattern

  25. this.state = { song: { title: 'Let it be', year:

    1970, }, }
  26. this.setState({ song: { title: 'Hey Jude', }, })

  27. State changes are shallow merged

  28. setState

  29. yarn add setstate - DON’T TRY THIS AT HOME -

  30. None
  31. “If setState was packaged up as a lib, people would

    love it.” @chantastic, Jul 2017
  32. setState enqueues changes to the component state and tells React

    that a component and its children need to be re-rendered with the updated state.
  33. setState enqueues changes to the component state and tells React

    that a component and its children need to be re-rendered with the updated state.
  34. setState(updater, [callback])

  35. (prevState, props) => stateChange

  36. setState(stateChange, [callback])

  37. Best practices

  38. @dan_abramov, Jul 2016

  39. this.state = { price: `${props.currency}${props.value}`, } Don’t

  40. this.setState({ request: API.get(...), }) Don’t

  41. Testing

  42. this.setState( (prevState, props) => ({ counter: prevState.counter + props.step, })

    )
  43. export const increment = (prevState, props) => ({ counter: prevState.counter

    + props.step, })
  44. import { increment } from './updaters' this.setState(increment)

  45. test('increment', () => { const prevState = { counter: 1

    } const props = { step: 1 } expect( increment(prevState, props) ).toEqual({ counter: 2 }) })
  46. test('increment', () => { const prevState = { counter: 1

    } const props = { step: 1 } expect( increment(prevState, props) ).toMatchSnapshot() })
  47. Separation of concerns

  48. • Container: data and behaviour • Presentational: appearance Container and

    Presentational
  49. componentDidMount() { API.get(...).then(s => this.setState(s)) } render() { return <Dumb

    {...this.state} /> }
  50. cb() { API.post(...).then(s => this.setState(s)) } render() { return <Dumb

    {...this.state} cb={this.cb} /> }
  51. yarn add react-fetching

  52. <ReactFetching url="https://api.punkapi.com/v2/beers" ok={beers => <h1>{beers[0].name}</h1>} />

  53. • Higher-order components • Component => Component • Options =>

    Component => Component Composition
  54. yarn add react-refetch

  55. connect(mapPropsToRequests)(Component)

  56. connect(() => ({ f: 'https://api.punkapi.com/v2/beers' }))( ({ f }) =>

    f.fulfilled ? <h1>{f.value[0].name}</h1> : null )
  57. Sharing state

  58. Do you even lift (your state up)?

  59. None
  60. None
  61. None
  62. componentDidMount() { API.get(...).then(s => this.setState(s)) } render() { return <div>{this.state.data}</div>

    }
  63. componentDidMount() { API.get(...).then(this.props.cb) } render() { return <div>{this.props.data}</div> }

  64. cb(data) { this.setState({ data }) } render() { return <Child

    {...this.state} cb={this.cb} /> }
  65. yarn add react-broadcast

  66. <Broadcast channel="state" value={this.state} > {this.props.children} </Broadcast>

  67. <Subscriber channel="state"> {state => ( <div>{state.data}</div> )} </Subscriber>

  68. Time travel

  69. yarn add --dev react-lumberjack

  70. None
  71. Lumberjack.back() Lumberjack.forward()

  72. Functional

  73. dispatch(action) { this.setState( prevState => reducer(prevState, action) ) }

  74. yarn add t-redux

  75. const reducer = buildReducer({ 'INCREMENT': state => ({ counter: state.counter

    + 1, }), }) const initialState = { counter: 0 }
  76. const inc = () => dispatcher.dispatch({ type: 'INCREMENT', }) const

    Button = ({ counter }) => ( <button onClick={inc}>{counter}</button> )
  77. withState([reducer], initialState)(Button)

  78. • Best practices • Testing • Separation of concerns •

    Sharing state • Time Travel • Functional Recap
  79. State Management

  80. • Higher-order components • Immutability • Pure functions • Generators

    • Observables Requirements
  81. • Make informed decisions about your tools • Understand the

    tradeoffs involved in each decision Choose wisely
  82. • react-redux uses setState • mobx-react uses forceUpdate Know your

    tools
  83. Takeaways

  84. Keep it simple

  85. Lift your state up

  86. Have fun!

  87. Michele Bertoli Front End Engineer at Facebook Author of React

    Design Patterns and Best Practices Follow me @MicheleBertoli