Установка состояния обработчика внутри React useEffect hook - PullRequest
0 голосов
/ 07 февраля 2020

Я пытаюсь создать пользовательский хук выборки данных для задания React из одного из моих курсов. Это простой способ доступа к нескольким конечным точкам REST API и создания объекта инвентаризации, который приложение использует для удобного создания компонента. Проблема в том, что я не могу установить внутреннее состояние ловушки из ловушки useEffect, которая выбирает данные. Я использовал этот подход много раз прежде, и я буквально не знаю, что вызывает такое поведение. Где бы я ни пытался использовать setContent внутри моей функции useEffect, она всегда остается null.

Пожалуйста, помогите!

const useInventory = (baseURL) => {
    const [loading, setLoading] = useState(false);
    const [content, setContent] = useState(null);
    const [error, setError] = useState(null);

    useEffect(() => {
        setLoading(true);

        const types = ['foundations', 'extras', 'proteins', 'dressings'];
        const urls = types.map(endp => `${baseURL}/${endp}`);

        Promise
            .all(urls.map(u => fetch(u)))
            .then(responses => Promise.all(responses.map(res => res.json())))
            .then(data => {

                const inventory = data.reduce((acc, curr, i) => 
                    ({ ...acc, [types[i]]: curr }),
                {});

                // This logs the inventory in desired format
                // e.g { foundations: Array, extras: Array, ... }
                console.log(inventory);
                setContent(inventory);
            })
            .catch(err => {
                setError(err);
            })
            .finally(() => {
                setLoading(false);

                // This logs null, for some reason
                console.log(content);
            });

    }, [baseURL]);

    return [content, loading, error];
}

Ответы [ 2 ]

0 голосов
/ 07 февраля 2020

попробуйте это пройдет

const useInventory = baseURL => {
  const [loading, setLoading] = useState(false);
  const [content, setContent] = useState(null);
  const [error, setError] = useState(null);

  useEffect(() => {
    setLoading(true);

    const types = ["foundations", "extras", "proteins", "dressings"];
    const urls = types.map(endp => `${baseURL}/${endp}`);
    function getData() {
      Promise.all(urls.map(u => fetch(u)))
        .then(responses => Promise.all(responses.map(res => res.json())))
        .then(data => {
          const inventory = data.reduce(
            (acc, curr, i) => ({ ...acc, [types[i]]: curr }),
            {}
          );

          // This logs the inventory in desired format
          // e.g { foundations: Array, extras: Array, ... }
          console.log(inventory);
          setContent(inventory);
        })
        .catch(err => {
          setError(err);
        });
    }

    getData();
  }, [baseURL, content]);

  console.log(content);
  return [content, loading, error];
};
`
0 голосов
/ 07 февраля 2020

Состояние установки не является синхронным, вы не получите обновленное содержимое в блоке finally.

Если вы хотите отладить значение изменений содержимого, вы можете использовать useEffect и консоль там, как показано ниже.

useEffect(() => {
  console.log(content); 
}, [content])
...