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
940
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.7k
Other Decks in Programming
See All in Programming
20250426 GDGoC 合同新歓 - GDGoC のススメ
getty708
0
110
カオスに立ち向かう小規模チームの装備の選択〜フルスタックTSという装備の強み _ 弱み〜/Choosing equipment for a small team facing chaos ~ Strengths and weaknesses of full-stack TS~
bitkey
1
140
Vibe Coding の話をしよう
schroneko
14
3.8k
AIコーディングの理想と現実
tomohisa
37
40k
Cursorを活用したAIプログラミングについて 入門
rect
0
200
GitHub Copilot for Azureを使い倒したい
ymd65536
1
330
KawaiiLT 登壇資料 キャリアとモチベーション
hiiragi
0
160
Laravel × Clean Architecture
bumptakayuki
PRO
0
150
MySQL初心者が311個のカラムにNot NULL制約を追加していってALTER TABLEについて学んだ話
hatsu38
2
140
flutter_kaigi_mini_4.pdf
nobu74658
0
150
ASP.NETアプリケーションのモダナイゼーションについて
tomokusaba
0
260
The Nature of Complexity in John Ousterhout’s Philosophy of Software Design
philipschwarz
PRO
0
170
Featured
See All Featured
The Power of CSS Pseudo Elements
geoffreycrofte
75
5.8k
RailsConf 2023
tenderlove
30
1.1k
Navigating Team Friction
lara
185
15k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
32
5.6k
Reflections from 52 weeks, 52 projects
jeffersonlam
349
20k
A better future with KSS
kneath
239
17k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
26k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
120
52k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
45
7.2k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
30
2.4k
The Pragmatic Product Professional
lauravandoore
33
6.6k
The Cost Of JavaScript in 2023
addyosmani
49
7.8k
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