У меня есть приложение React Native, в котором я запускаю некоторый код, похожий на код ниже. Почему следующий вывод undefined
? Чтение someState
из useEffect
равно undefined
, даже если состояние установлено внутри useEffect
const SomeComponent = () => {
const [someState,setSomeState] = useState();
const anFunction = () => {
let data = 'data'
return data
}
useEffect(() => {
const theData = anFunction();
setSomeState(theData)
console.info(someState)
},[])
...
// later renders some component
}
Я пытаюсь установить состояние, а затем прочитать состояние внутри этого useEffect
, потому что я хотел бы реализовать что-то вроде:
const doSomethingWithTheState = () => {
//some transformation here
setSomeState(transformedData)
}
useEffect(() => {
const theData = anFunction();
setSomeState(theData)
doSomethingWithTheState()
},[])
Обновления состояния в useEffect
не синхронны, и ваш console.info
ссылается на текущее состояние, а не на обновленное состояние. См. это сообщение: stackoverflow.com/questions/54069253/…
Это должно работать, добавляя .then
.then(doSomethingWithTheState())
Это не определено, потому что useEffect
не async
. Ваше начальное состояние уже undefined
, поэтому вы видите undefined
в console.info
. Чтобы создать асинхронную логику внутри useEffect
, вы должны обновить вот так
useEffect(() => {
async function test(){
//Your logic here
}
test()
},[])
Вы можете что-то почерпнуть из моего ответа на аналогичный вопрос: React Native Я не могу сохранить массив с помощью AsyncStorage
@gloo разместил гораздо более интересное обсуждение этой проблемы здесь: Метод set useState не отражает изменения немедленно
Состояние настройки не является ни синхронным, ни асинхронным. Это причуда/особенность экосистемы React. Состояние неизменно с точки зрения одного рендера; поэтому вы никогда не получите обновленное состояние до следующего рендеринга.
Если вам нужно работать с состоянием сразу после его изменения, делайте это в useEffect с переменной состояния в массиве зависимостей.
между вашим ответом и ответом gloos я смог собрать воедино решение о наличии состояния для функции useEffect
. Немного раздражающее поведение со стороны React, но тем не менее очень интересное.
Я отредактировал ссылку @gloo в своем ответе, потому что считаю, что это гораздо более интересное и полное обсуждение проблемы. Я буду связывать это с этого момента. Спасибо!
Поскольку моя цель — изменить данные в useEffect
, было лучше инициализировать мое состояние с помощью anFunction()
(очевидно, это всего лишь пример). Вот как теперь выглядит мой код:
const SomeComponent = () => {
const [someState,setSomeState] = useState(anFunction());
const anFunction = () => {
let data = 'data'
return data
}
useEffect(() => {
console.info(someState)
},[])
...
// later renders some component
}
Я видел разговор о том, что useState является асинхронным. Это заблуждение. Глядя на ответ Эйба и его описание, вы сможете решить множество странных ситуаций, связанных с установкой состояний React.
Не пытайтесь await
или async
настроить свое состояние в useEffect
.
Вызов
setSomeState
запускает обновление состояния, но вы не видите обновленное состояние до следующего повторного рендеринга компонента. Если вы хотите, чтобы какое-то действие запускалось при каждом измененииsomeState
, вы должны поместить его в отдельныйuseEffect
сsomeState
в массиве зависимостей.