UseState всегда показывает предыдущее значение
Это популярный вопрос среди всех новых разработчиков, но почему-то я не могу понять логику имеющихся решений. Я пытаюсь обновить переменную состояния с помощью хуков и пытаюсь прочитать обновленное значение, но всегда возвращает предыдущее значение вместо нового значения. Ниже представлена последовательность выполнения моего кода.
onClick={setTransactionAccountId}
при нажатии кнопки выполняется приведенный ниже код и обновляется состояние, но console.log
показывает старое значение.
const [accountId, setAccountId] = useState(0);
const setTransactionAccountId = e => {
console.log("Clicked ID:", e.currentTarget.value);
setAccountId(e.currentTarget.value);
console.log("accountId:", accountId);
};
журнал консоли:
- первое нажатие кнопки:
Нажмите ID: 0 accountId: 0
- нажатие второй кнопки:
Нажмите ID: 1 accountId: 0
может ли кто-нибудь рассказать мне причину такого поведения и как с этим бороться.
3 ответа
accountId
не будет обновлен этот рендер. Вам нужно дождаться следующего рендера, чтобы он обновился. accountId
заполняется только в верхней части функционального компонента, когда useState
называется. Вы в середине рендера. Если вам нужна реальная стоимость, продолжайте вытаскивать ее изe.currentTarget.value
.
React может объединять несколько вызовов setState() в одно обновление для повышения производительности.
Поскольку this.props и this.state могут обновляться асинхронно, вам не следует полагаться на их значения при вычислении следующего состояния.
Обновления состояния могут группироваться и обновляться асинхронно, поэтому состояние могло не обновляться при вызове console.log(). Вы получите гарантированно обновленный результат при следующем вызове хука useEffect.
Это потому что setState
асинхронный. Выполнениеconsole.log('accountId:', accountId)
до обновления состояния по-прежнему будет давать вам предыдущее значение состояния. Если вы добавите async/await, это должно решить проблему.
const setTransactionAccountId = async (e) => {
console.log('Clicked ID:', e.currentTarget.value)
await setAccountId(e.currentTarget.value)
console.log('accountId:', accountId)
}