Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
setState ftw
Search
Michele Bertoli
October 06, 2017
Programming
12
3.6k
setState ftw
"Nobody knows how to do anything without Redux anymore. It's ridiculous." - @mjackson
Let's fix it!
Michele Bertoli
October 06, 2017
Tweet
Share
More Decks by Michele Bertoli
See All by Michele Bertoli
setState Machine
michelebertoli
10
1.8k
Test Like It's 2017
michelebertoli
3
860
Painless Testing
michelebertoli
2
170
Proper Error Handling
michelebertoli
10
1.7k
CSS in JS
michelebertoli
0
610
Inline Styles
michelebertoli
6
780
UNLEARN EVERYTHING
michelebertoli
5
1.7k
Other Decks in Programming
See All in Programming
CPython 인터프리터 구조 파헤치기 - PyCon Korea 24
kennethanceyer
0
220
offers_20241022_imakiire.pdf
imakurusu
2
310
Kaigi on Rails 2024 - Rails APIモードのためのシンプルで効果的なCSRF対策 / kaigionrails-2024-csrf
corocn
4
2.8k
僕がつくった48個のWebサービス達
yusukebe
17
16k
Why Spring Matters to Jakarta EE - and Vice Versa
ivargrimstad
0
610
JaSST 24 九州:ワークショップ(は除く)実践!マインドマップを活用したソフトウェアテスト+活用事例
satohiroyuki
0
170
2万ページのSSG運用における工夫と注意点 / Vue Fes Japan 2024
chinen
3
1.3k
詳細解説! ArrayListの仕組みと実装
yujisoftware
0
430
役立つログに取り組もう
irof
24
7.7k
生成 AI を活用した toitta 切片分類機能の裏側 / Inside toitta's AI-Based Factoid Clustering
pokutuna
0
530
Kubernetes for Data Engineers: Building Scalable, Reliable Data Pipelines
sucitw
1
180
C#/.NETのこれまでのふりかえり
tomokusaba
1
140
Featured
See All Featured
Keith and Marios Guide to Fast Websites
keithpitt
408
22k
Visualization
eitanlees
143
15k
Designing for Performance
lara
604
68k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
228
52k
Large-scale JavaScript Application Architecture
addyosmani
510
110k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
664
120k
RailsConf 2023
tenderlove
29
870
jQuery: Nuts, Bolts and Bling
dougneiner
61
7.5k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
26
2k
Why Our Code Smells
bkeepers
PRO
334
57k
What's new in Ruby 2.0
geeforr
342
31k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
31
2.6k
Transcript
setState ftw @MicheleBertoli
My name’s Michele and I’m a React fanboy since 2014
I work in Ads at Facebook, and I contribute to
a pretty sophisticated React UI
setState is the primary method you use to update the
UI in React
Are we really going to talk about setState for 40
minutes?
YES
Ok, why?
“I’m learning React but I don’t understand reducers.” Anonymous, Mar
2017
react
react-redux redux react react-router react-router-redux
react-redux redux react react-router react-router-redux
The community
“Nobody knows how to do anything without Redux anymore. It's
ridiculous.” @mjackson, Jun 2016
“3 Reasons why I stopped using React.setState.” @mweststrate, Jun 2016
“I love setState. In 3 1/2 years, I haven't needed
anything more.” @chantastic, Mar 2017
“You might not need Redux.” @dan_abramov, Sep 2016
Common Pitfalls
setState({ title: 'Here comes the sun' }) console.log(this.state.title)
setState is asynchronous
setState({ counter: this.state.counter + 1 }) setState({ counter: this.state.counter +
1 })
Object.assign( prevState, { counter: this.state.counter + 1 }, { counter:
this.state.counter + 1 }, )
Multiple setState calls get batched
this.state.title = 'Come together'
Mutating the state is an anti-pattern
this.state = { song: { title: 'Let it be', year:
1970, }, }
this.setState({ song: { title: 'Hey Jude', }, })
State changes are shallow merged
setState
yarn add setstate - DON’T TRY THIS AT HOME -
None
“If setState was packaged up as a lib, people would
love it.” @chantastic, Jul 2017
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.
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.
setState(updater, [callback])
(prevState, props) => stateChange
setState(stateChange, [callback])
Best practices
@dan_abramov, Jul 2016
this.state = { price: `${props.currency}${props.value}`, } Don’t
this.setState({ request: API.get(...), }) Don’t
Testing
this.setState( (prevState, props) => ({ counter: prevState.counter + props.step, })
)
export const increment = (prevState, props) => ({ counter: prevState.counter
+ props.step, })
import { increment } from './updaters' this.setState(increment)
test('increment', () => { const prevState = { counter: 1
} const props = { step: 1 } expect( increment(prevState, props) ).toEqual({ counter: 2 }) })
test('increment', () => { const prevState = { counter: 1
} const props = { step: 1 } expect( increment(prevState, props) ).toMatchSnapshot() })
Separation of concerns
• Container: data and behaviour • Presentational: appearance Container and
Presentational
componentDidMount() { API.get(...).then(s => this.setState(s)) } render() { return <Dumb
{...this.state} /> }
cb() { API.post(...).then(s => this.setState(s)) } render() { return <Dumb
{...this.state} cb={this.cb} /> }
yarn add react-fetching
<ReactFetching url="https://api.punkapi.com/v2/beers" ok={beers => <h1>{beers[0].name}</h1>} />
• Higher-order components • Component => Component • Options =>
Component => Component Composition
yarn add react-refetch
connect(mapPropsToRequests)(Component)
connect(() => ({ f: 'https://api.punkapi.com/v2/beers' }))( ({ f }) =>
f.fulfilled ? <h1>{f.value[0].name}</h1> : null )
Sharing state
Do you even lift (your state up)?
None
None
None
componentDidMount() { API.get(...).then(s => this.setState(s)) } render() { return <div>{this.state.data}</div>
}
componentDidMount() { API.get(...).then(this.props.cb) } render() { return <div>{this.props.data}</div> }
cb(data) { this.setState({ data }) } render() { return <Child
{...this.state} cb={this.cb} /> }
yarn add react-broadcast
<Broadcast channel="state" value={this.state} > {this.props.children} </Broadcast>
<Subscriber channel="state"> {state => ( <div>{state.data}</div> )} </Subscriber>
Time travel
yarn add --dev react-lumberjack
None
Lumberjack.back() Lumberjack.forward()
Functional
dispatch(action) { this.setState( prevState => reducer(prevState, action) ) }
yarn add t-redux
const reducer = buildReducer({ 'INCREMENT': state => ({ counter: state.counter
+ 1, }), }) const initialState = { counter: 0 }
const inc = () => dispatcher.dispatch({ type: 'INCREMENT', }) const
Button = ({ counter }) => ( <button onClick={inc}>{counter}</button> )
withState([reducer], initialState)(Button)
• Best practices • Testing • Separation of concerns •
Sharing state • Time Travel • Functional Recap
State Management
• Higher-order components • Immutability • Pure functions • Generators
• Observables Requirements
• Make informed decisions about your tools • Understand the
tradeoffs involved in each decision Choose wisely
• react-redux uses setState • mobx-react uses forceUpdate Know your
tools
Takeaways
Keep it simple
Lift your state up
Have fun!
Michele Bertoli Front End Engineer at Facebook Author of React
Design Patterns and Best Practices Follow me @MicheleBertoli