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.7k
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.9k
Test Like It's 2017
michelebertoli
3
950
Painless Testing
michelebertoli
2
190
Proper Error Handling
michelebertoli
10
1.8k
CSS in JS
michelebertoli
0
650
Inline Styles
michelebertoli
6
830
UNLEARN EVERYTHING
michelebertoli
5
1.8k
Other Decks in Programming
See All in Programming
TypeScript エンジニアが Android 開発の世界に飛び込んだ話
yuisakamoto
6
950
eBPFを用いたAIネットワーク監視システム論文の実装 / eBPF Japan Meetup #4
yuukit
3
610
型付け力を強化するための Hoogle のすゝめ / Boosting Your Type Mastery with Hoogle
guvalif
1
230
ワイがおすすめする新潟の食 / 20250530phpconf-niigata-eve
kasacchiful
0
180
Agent Rules as Domain Parser
yodakeisuke
1
330
Perlで痩せる
yuukis
1
650
OpenTelemetryで始めるベンダーフリーなobservability / Vendor-free observability starting with OpenTelemetry
seike460
PRO
0
160
CQRS/ESのクラスとシステムフロー ~ RailsでフルスクラッチでCQRSESを組んで みたことから得た学び~
suzukimar
0
190
テスト分析入門/Test Analysis Tutorial
goyoki
11
2.7k
#QiitaBash TDDでAIに設計イメージを伝える
ryosukedtomita
2
1.6k
RubyKaigi Hack Space in Tokyo & 函館最速 "予習" 会 / RubyKaigi Hack Space in Tokyo & The Fastest Briefing of RubyKaigi 2026 in Hakodate
moznion
1
120
primeNumberでのRBS導入の現在 && RBS::Traceでinline RBSを拡充してみた
mnmandahalf
0
250
Featured
See All Featured
[RailsConf 2023] Rails as a piece of cake
palkan
55
5.6k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
8
750
Testing 201, or: Great Expectations
jmmastey
42
7.5k
We Have a Design System, Now What?
morganepeng
52
7.6k
Six Lessons from altMBA
skipperchong
28
3.8k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
26k
Keith and Marios Guide to Fast Websites
keithpitt
411
22k
VelocityConf: Rendering Performance Case Studies
addyosmani
329
24k
It's Worth the Effort
3n
184
28k
What’s in a name? Adding method to the madness
productmarketing
PRO
22
3.5k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
25
2.8k
A Modern Web Designer's Workflow
chriscoyier
693
190k
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