Эффект использования реакции зависит от значения, которое инициализируется после вызова api

#reactjs #react-hooks

#reactjs #реагирующие крючки

Вопрос:

Мой api возвращает объект следующего типа:

 type TApiReturn = {
  a: string;
  b?: string;
  c?: string;
  d?: string;
};
 

Теперь, после получения данных, я хочу передать их часть дочернему компоненту.

 type TChildComponent = {
a: string;
c?: string;
};
 

То, что я думал, сработает:

 const [allData, setAllData] = React.useState<TApiReturn>();
const [childData, setChildData = React.useState<TChildComponent>();

useEffect(() => {
    const fetchData = async () => {
      const result = await api.get('myDataPath'); //this works, not part of it
      setData(result.data);
    };

    fetchData();
  }, []);
 

а затем, чтобы обновить данные дочернего компонента:

 useEffect(() => {
    let parsedData: TChildComponent;
    parsedData.a = data.a;
    
    if (data.c) {
      parsedData.c = data.c;
    } 
  
    setChildData(parsedData);
  }, [allData.a]);
 

Но да, это не может работать, поскольку в начале allData.a находится undefined в начале.

Итак, подводя итог: я не уверен, как подойти к этой ситуации. Я понимаю, что у перехватчиков нет функции обратного вызова специально. Но эта ситуация кажется вполне нормальной, поэтому должен быть лучший шаблон проектирования для решения этой проблемы, которого я не вижу.

Ответ №1:

Поскольку состояние должно быть неизменяемым в React, вместо того, чтобы иметь массив зависимостей allData.a , allData может работать только зависимость от (и затем вы можете проверить, allData существует ли, и если да, для allData.a сравнения childDate.a ).

Но я думаю, что лучшим подходом было бы не разделять одну и ту же структуру данных на несколько переменных с отслеживанием состояния, а просто передавать allData.a , когда она существует, например:

 const [allData, setAllData] = React.useState<TApiReturn>();
// no childData at all

// ...

return (
  <Child a={allData?.a} c={allData?.c} />
);
 

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

1. Спасибо. Но когда я попробую предложенный вами подход (передаю данные, если они существуют) Я всегда получаю Object is possibly 'undefined'. TS2532 .

2. Что бы вы хотели, чтобы произошло, когда данные могут еще не существовать и дочерний элемент должен быть визуализирован?

3. Ну, я обернул весь компонент условно, {allData amp;amp; <Дочерний элемент …>} .

4. Если он отображается условно, было бы неплохо просто удалить необязательную цепочку, например: a={allData.a} c={allData.c}

5. Ну, мой линтер жалуется в любом случае. До сих пор я мог обойти TS2532 только путем инициализации allData с null помощью . Я должен разобраться в этом, похоже, подход, который приведет к нежелательным ошибкам. Кроме того, как бы я справился с этим, если бы я не использовал условный рендеринг?