为什么我的自定义钩子使用一次后会执行两次?

김경한*_*김경한 0 reactjs react-hooks

嗨,我正在学习 React,当我制作这个例子时,我感到有些好奇。这段代码就是向newsapi发送get请求,并接收结果。我使用了自定义钩子。

// *** this is where I use custom hook. "usePromise" is custom hook. *** //
function NewsList({ category }) {
  const [loading, response, error] = usePromise(() => {
    console.log("how many will it run?")
    const query = category === 'all' ? '' : `&category=${category}`;
    return axios.get(
      `https://newsapi.org/v2/top-headlines?country=kr${query}&apiKey=044c3c345f28417380cd3ea946ac8641`
    );
  },[category]); 

  console.log(loading);

...

Run Code Online (Sandbox Code Playgroud)

我写了 console.log("how much will it run?") 来检查这个函数将运行多少个。还有console.log(loading)来检查加载将被更改的次数

// *** this is custom hook's code *** //
export default function usePromise(promiseCreator, deps) {
  const [loading, setLoading] = useState(true);
  const [response, setResponse] = useState(null);
  const [error, setError] = useState(null);

  useEffect(() => {
    const process = async () => {
      await promiseCreator()
        .then((res) => {
          setResponse(res);
        })
        .catch((e) => {
          console.log('catch');
          setError(e);
        });
      setLoading(false);
    };
    process();
  }, deps);
  return [loading, response, error];
}
Run Code Online (Sandbox Code Playgroud)

我写了 console.log('catch') 来检查这个 Promise 函数将启动多少个。(顺便说一句,发送太多请求的原因,当我发送请求时,此代码出现“错误”)

// *** this is the console when I run this project on browser *** //
NewsList.jsx:31 true
NewsList.jsx:24 how many will it run?
NewsList.jsx:24 how many will it run?
usePromise.js:15 catch
NewsList.jsx:31 false
usePromise.js:15 catch
NewsList.jsx:31 false
Run Code Online (Sandbox Code Playgroud)

如你看到的。usePromise 被执行两次。我知道加载将被控制台两次,“true”和“false”,因为 usePromise 中的函数是异步的。但我不知道为什么usePromise执行了两次。我预计它会在声明时执行一次。

如果你知道答案请为我评论。这对我有很大帮助,谢谢

Jak*_*lek 7

您使用的是吗<StrictMode>?如果是,则严格模式被设计为运行效果两次。

\n

严格模式用于检测效果中可能存在的错误,还用于检测代码中的其他问题,这些问题会阻止您轻松升级到下一个版本的 React。您的效果应该能够适应它,调用它们两次不会导致代码中出现错误,即使这意味着您的 API 被调用两次。在生产中,它不执行任何操作,它只是一个开发工具。

\n

在这种情况下,它试图指出您的效果存在问题,例如它没有清理阶段。如果由于依赖项更改或组件卸载而导致效果被清除,那么您将遇到问题(例如在已卸载的组件上调用 setState)。

\n

清理示例:

\n
useEffect(() => {\n  // use local flag\n  let cleanup = false\n\n  const process = () => {\n    Promise.resolve(true).then(() => {\n      // check if cleanup has been run\n      if (!cleanup) {\n        setState(true)\n     \xc2\xa0}\n    })\n  }\n\n  process()\n\n  // set the flag\n  return () => {\n    cleanup = true\n  }\n}, [])\n
Run Code Online (Sandbox Code Playgroud)\n