Используя перехватчики реакции, используя «useState» и «useEffect», есть ли способ отобразить состояние ожидания, пока состояние не получит значение?

#javascript #reactjs #react-hooks #use-effect #use-state

#javascript #reactjs #реагирующие перехваты #use-effect #use-state

Вопрос:

Что я пытаюсь сделать?

Рендеринг characterInfo с помощью реактивных перехватов во внешнем интерфейсе.

Какой код в настоящее время пытается это сделать?

Интерфейсный компонент отображает информацию:

 export default function ReactComponent() {
  const [characterInfo, setCharacterInfo] = useState([]);

  useEffect(() => {
    socket.emit("/character/read");
    socket.on("/character/read", function (data) {
      if (data.status === "SUCCESS") {
        setCharacterInfo(data)
      }
    });
    return () => {
      socket.off("/character/read");
    };
  }, []);

  return (
    <div>
      {characterInfo.models[0].name}
    </div>
  )
}
  

Внутренняя .json информация как «данные», а также то, что сохраняется с characterInfo помощью setCharacterInfo :

 {
  status: "SUCCESS"
  models: [
    { 
      name: "AC",
      element: "Air",
    }
    {
      name: "Irene",
      element: "Fire",
    }
  ]
}
  

(так что в этом случае для доступа к «AC» это было бы characterInfo.models[0].name )

Каким я ожидаю результата?

Я ожидаю, что оно просто AC будет отображено.

Каков фактический результат?

Я бы получил эту ошибку:

TypeError: Cannot read property '0' of undefined

В чем, я думаю, может быть проблема?

Я думаю, что это связано с асинхронной балансировкой, особенно с useEffect() . Я думаю, что интерфейс пытается выполнить рендеринг, прежде setCharacterInfo чем решит что-либо установить.

Комментарии:

1. Вам нужно просмотреть свои результаты. С помощью чего-то вроде «map’ при его рендеринге

2. Кроме того, ваши данные настройки как часть вашего состояния, когда для вашего состояния установлено значение characterInfo

3. Для первого комментария, если вы говорите {characterInfo.models.map((model) => (<div>{model.name}</div>))} , ошибка, которую я получу, относится TypeError: Cannot read property 'map' of undefined'. ко второму комментарию, да, я помещаю «данные» в setCharacterInfo состояние, тогда «данные» должны быть моим characterInfo состоянием.

Ответ №1:

Я думаю, что интерфейс пытается выполнить рендеринг до того, как setCharacterInfo решит вообще что-либо установить.

Это правильно, ваш компонент отображается один раз со useState значением по умолчанию перед запуском функции useEffect . Вот диаграмма порядка выполнения при подключении, обновлении и отключении компонента (примечание render происходит раньше useEffect ):

https://raw.githubusercontent.com/donavon/hook-flow/master/hook-flow.png

Вам нужно будет проверить, characterInfo.models существует ли оно (и, чтобы быть в безопасности, убедитесь, что оно имеет длину) перед доступом name .

   return (
    <div>
      {
        characterInfo.models amp;amp;
        characterInfo.models.length amp;amp;
        characterInfo.models[0].name
      }
    </div>
  )
  

Или, если вы используете необязательную цепочку:

   return (
    <div>
      {characterInfo?.models[0]?.name}
    </div>
  )
  

Еще одно замечание — вы устанавливаете начальное значение characterInfo в пустой массив. Если вы сделаете его пустым объектом, будет яснее, что вы ожидаете data быть объектом, а не массивом.

 const [characterInfo, setCharacterInfo] = useState({});
  

Комментарии:

1. Я попробовал первое решение, и интерфейс ничего не отображал. Я сделал a console.log для каждого из значений, и вот что последовало : [{...}], undefined, "AC" . Теперь, когда я попробовал просто {characterInfo.models amp;amp; characterInfo.models[0].name} , это сработало! Я попробовал второе решение, и это привело к той же проблеме TypeError: Cannot read property '0' of undefined . Я пошел дальше и сделал вашу заметку, которую, на мой взгляд, полезно использовать. Спасибо за вашу помощь!

Ответ №2:

Вы можете настроить свой оператор return так, чтобы отображать имя только в том случае, если / когда оно существует

 return (
    <div>
      {characterInfo.length amp;amp; characterInfo.models[0].name}
    </div>
  )
  

Комментарии:

1. Решение не сработало для меня, я углубился, чтобы посмотреть, какие значения отображаются с помощью кнопки, которая console.log(characterInfo.length) и console.log(characterInfo.models[0].name) , первая будет отображаться undefined , а вторая будет отображаться "AC" . Спасибо за попытку!