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
930
Painless Testing
michelebertoli
2
190
Proper Error Handling
michelebertoli
10
1.8k
CSS in JS
michelebertoli
0
640
Inline Styles
michelebertoli
6
820
UNLEARN EVERYTHING
michelebertoli
5
1.7k
Other Decks in Programming
See All in Programming
これだけは知っておきたいクラス設計の基礎知識 version 2
masuda220
PRO
24
6.5k
API for docs
soutaro
2
1.4k
複雑なフォームの jotai 設計 / Designing jotai(state) for Complex Forms #layerx_frontend
izumin5210
4
1.1k
Being an ethical software engineer
xgouchet
PRO
0
210
AIコーディングワークフローの試行 〜AIエージェント×ワークフローでの自動化を目指して〜
rkaga
3
3.7k
Dissecting and Reconstructing Ruby Syntactic Structures
ydah
1
750
Making TCPSocket.new "Happy"!
coe401_
1
1.6k
一緒に働きたくなるプログラマの思想 #QiitaConference
mu_zaru
51
13k
RuboCop: Modularity and AST Insights
koic
2
1.4k
Cursor/Devin全社導入の理想と現実
saitoryc
15
9.6k
Do Dumb Things
mitsuhiko
0
440
プロフェッショナルとしての成長「問題の深掘り」が導く真のスキルアップ / issue-analysis-and-skill-up
minodriven
7
1.5k
Featured
See All Featured
Documentation Writing (for coders)
carmenintech
69
4.7k
Typedesign – Prime Four
hannesfritz
41
2.6k
Into the Great Unknown - MozCon
thekraken
37
1.7k
Build The Right Thing And Hit Your Dates
maggiecrowley
35
2.6k
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
3.8k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
47
5.3k
Being A Developer After 40
akosma
91
590k
Thoughts on Productivity
jonyablonski
69
4.6k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
47
2.7k
Facilitating Awesome Meetings
lara
54
6.3k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
31
1.1k
4 Signs Your Business is Dying
shpigford
183
22k
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