Состояние в useEffect не определено после того, как useEffect устанавливает состояние?

У меня есть приложение 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()

  },[])

Вызов setSomeState запускает обновление состояния, но вы не видите обновленное состояние до следующего повторного рендеринга компонента. Если вы хотите, чтобы какое-то действие запускалось при каждом изменении someState, вы должны поместить его в отдельный useEffect с someState в массиве зависимостей.

super 05.05.2022 23:34

Обновления состояния в useEffect не синхронны, и ваш console.info ссылается на текущее состояние, а не на обновленное состояние. См. это сообщение: stackoverflow.com/questions/54069253/…

gloo 05.05.2022 23:35
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
0
2
51
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Это должно работать, добавляя .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, но тем не менее очень интересное.

patataskr 06.05.2022 19:15

Я отредактировал ссылку @gloo в своем ответе, потому что считаю, что это гораздо более интересное и полное обсуждение проблемы. Я буду связывать это с этого момента. Спасибо!

Abe 09.05.2022 06:41

Поскольку моя цель — изменить данные в 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.

Другие вопросы по теме