Functional setState()
Class Component
State is assigned using the class constructor
class Kitten extends Component {
constructor() {
super()
this.state = {
name: ''
};
...
}
render() {
return (
<div>
<h1>Meow, it's {this.state.name}'s Homepage</h1>
</div>
<div className="kitten">
<img src={kitten} alt="cute kitten" />
</div>
);
}
}setState()
with Object
Update state by passing an object containing part of the state to setState()
class Kitten extends React.Component {
...
setKittenName(name) {
this.setState({
name: name
});
}
componentWillMount() {
this.setKittenName('Greg');
}
render() {
...
}
}
But what if your next state depends on the previous state?
Invoking setState() multiple times
class Puppy extends Component {
constructor() {
super()
this.state = {
name: '',
treats: 0
};
...
}
twoTreats() {
this.setState({
treats: this.state.treats + 1
});
this.setState({
treats: this.state.treats + 1
});
}
...
render() {
return (
...
<h2>I want two treats!</h2>
<div>
<button onClick={this.twoTreats}>
Two treats please!
</button>
<div><h3>{this.state.treats}</h3></div>
</div>
...
);
}
}Demo of bad setState() example
React merges multiple setState() calls together form a single object
Object Composition
let puppy = { name: 'Fido' },
dog = { name: 'Fluffy' },
tiger = Object.assign({}, puppy, dog);
console.log(tiger); // { name: 'Fluffy' }When merging multiple objects with the same key, the value of the last object overrides the previous values
How can we fix our problem?
Functional
setState()!
Dan Abramov said so himself

First,
- Move your methods to a class component and pass them down as props.
- Also pass down key items from the state as props
class App extends React.Component {
constructor() {
super()
this.state = {
name: '',
treats: 0
};
}
...
twoTreats() {
this.setState({
treats: this.state.treats + 1
});
this.setState({
treats: this.state.treats + 1
});
}
render() {
return (
<Puppies twoTreats={this.twoTreats}
treats={this.state.treats}
/>
)
}
}
}Second
Refactor this.setState() to pass in a function that accepts the previous state and a callback function as a second parameter
twoTreats() {
this.setState((prevState, props) => ({
treats: prevState.treats +1
}));
this.setState((prevState, props) => ({
treats: prevState.treats +1
}));
}
Third
Refactor the presentational component to use twoTreats() from props
const Puppies = (props) => {
return (
...
</div>
<h2>I want two treats!</h2>
<div>
<button
onClick={props.twoTreats}>Two treats please!
</button>
<div><h3>{props.treats}</h3></div>
</div>
...
);
}Demo of good setState()
Resources
- Link
- Link
- Link
Functional setState()
By Fanny Jiang
Functional setState()
Learn about how to use functional setState to manage the state of your React app.
- 138