В предыдущей версии реагирования мы могли выполнить код после изменения состояния, выполнив что-то вроде:
setState( prevState => {myval: !prevState.myval}, () => {
console.log("myval is changed now");
)
И убедитесь, что второй «бит» выполняется только с обновленным кодом. Теперь один из примеров описывает что-то «похожее» может быть достигнуто с помощью React.useEffect
:
const [myval, setMyval] = React.useState(false);
React.useEffect(() => {
console.log("myval is changed now");
}
//somewhere
setMyval(o => !o);
Хотя это выглядит прекрасно и модно, в моем случае это не поможет: в моем случае «какой эффект нужен произойти "зависит от того места, где состояние изменилось, изначально:
//somewhere
setState( prevState => {myval: !prevState.myval}, () => {
console.log("myval is changed now");
)
//somewhere else
setState( prevState => {myval: !prevState.myval}, () => {
console.log("myval has changed somewhere else");
)
Изменение их на useState
+ setMyval
позволит одному и тому же эффекту сработать в обеих позициях, поэтому мы не можем получить в useEffect какое действие на самом деле должно произойти.
Как бы я поступил выше в компоненте функции, основанной на перехвате?
Лучшим вариантом использования был бы экран с двумя кнопками, одна для загрузки предыдущей еще один, чтобы загрузить следующий. Кнопки отключены, пока isLoading
состояние истинно и выполняет действия только при загрузке. Чтобы гарантировать, что может произойти только одна загрузка, мы не можем просто «действовать», как если бы состояние изменялось немедленно: изменение состояния происходит асинхронно, и, следовательно, может возникать состояние гонки.
Использование обратного вызова при изменении состояния предотвращает это состояние гонки и обеспечивает только одну загрузку:
class SomScreen extends React.component {
state = { isLoading: false }
render() {
<div>
<button
disabled={this.state.isLoading}
onclick={(e) => {
if (!this.state.isLoading) {
this.setState((p) => ({isLoading: true}), () => {
await fetchPreviousDataAndDoSomethingWithIt()
setState({isLoading: false});
});
}
}
/>Previous</button>
<button
disabled={this.state.isLoading}
onclick={(e) => {
if (!this.state.isLoading) {
this.setState((p) => ({isLoading: true}), () => {
await fetchNextDataAndDoSomethingWithIt()
setState({isLoading: false});
});
}
}
/>Next</button>
</div>
}
}