简体   繁体   English

在 React useEffect 钩子中设置钩子状态

[英]Setting hook state inside React useEffect hook

I'm trying to create a custom data fetching hook for a React assignment from one of my courses.我正在尝试为我的一门课程中的 React 作业创建自定义数据获取挂钩。 Is's a simple hook accessing a couple of REST API endpoints and creating an inventory object which the app uses for a sallad composing component.是一个简单的钩子,它访问几个 REST API 端点并创建一个清单对象,应用程序将其用于组成沙拉的组件。 The problem is that I can't seem to set the internal state of the hook from within the useEffect hook which fetches the data.问题是我似乎无法从获取数据的useEffect钩子中设置钩子的内部状态。 I've used this approach many times before, and I have literally no idea what causes this behaviour.我以前多次使用过这种方法,我真的不知道是什么导致了这种行为。 Wherever i try to use setContent inside my useEffect function, it always remains null .无论我在哪里尝试在useEffect函数中使用setContent ,它始终保持为null

Please help!请帮忙!

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];
}

Setting state is not synchronous you won't get updated content in finally block.设置状态不是同步的,您不会在 finally 块中获得更新的内容。

If you want to debug value of content changes you can use useEffect and console there like below.如果您想调试内容更改的值,您可以使用 useEffect 和控制台,如下所示。

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

try this it will be pass试试这个它会通过

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];
};
`

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM