Функция обновления состояния необходима как для класса, так и для функциональных компонентов.this.setState
не следует использовать вместе с this.state
, то же самое относится к useState
состоянию и установщику состояний.В useState
есть еще случаи, когда не используется средство обновления состояний, что приведет к неправильному поведению.
В компонентах класса единственной проблемой при использовании this.state
является состояние гонки из-за асинхронных обновлений состояния:
componentDidMount() {
this.setState({ count: this.state.count + 1 });
this.setState({ count: this.state.count + 1 }); // overwrites with stale count
console.log(this.state.count); // not updated
}
Когда нет условий гонки, можно получить доступ к this.state
в любом месте внутри компонента, поскольку ссылка this
остается неизменной:
componentDidMount() {
this.setState({ count: this.state.count + 1 });
setTimeout(() => {
this.setState({ count: this.state.count + 1 });
}, 100)
setTimeout(() => {
console.log(this.state.count);
}, 200)
}
В функциональных компонентах проблема сиспользование состояния useState
является областью действия функции.Нет такого объекта, к которому можно было бы обратиться по ссылке, состояние доступно по значению, которое не будет обновлено, пока компонент не будет перерисован:
const [count, setCount] = useState(0);
useEffect(() => {
// runs once on mount
// count is always 0 in this function scope
setCount({ count: count + 1 });
setTimeout(() => {
setCount({ count: count + 1 }); // overwrites with stale count
}, 100)
setTimeout(() => {
console.log(count); // not updated
}, 200)
}, []);