React自定义hook无限渲染

我制作了一个自定义钩子,用于获取新闻 API 并返回用于加载、错误和数据的处理程序(受到 Apollo Client 的启发)。问题是,当使用它时,即使依赖项数组中的项目没有改变,它也会无限地自行触发。这就是我的实现方式:


钩子:


const useSearch = (query: string, sources: string[]) => {

  const [response, setResponse] = useState<State>({

    data: null,

    loading: true,

    error: null,

  });


  useEffect(() => {

    newsapi

      .getEverything({

        q: query,

        pageSize: 1,

        sources: sources,

      })

      .then((data) => {

        setResponse({ data, loading: false, error: null });

      })

      .catch((e) => {

        setResponse({ data: null, loading: false, error: e });

      });

  }, [query, sources]);


  return response;

};

用法:


  const { loading, error, data } = useSearch("Donald", ["bbc-news"]);

我超出了 API 的每日费率:

https://img4.mukewang.com/65152e8100011a8808290022.jpg

我究竟做错了什么?



慕仙森
浏览 83回答 1
1回答

拉风的咖菲猫

我提供了解决方案,@JacobSmit 在评论部分进行了解释。现在我只是把它们整理成一个更详细的答案,希望对后来者有所帮助。解决方案const useSearch = (query: string, sources: string[]) => {&nbsp; // ...&nbsp; useEffect(() => {&nbsp; &nbsp; // ...&nbsp; &nbsp; // FIX:&nbsp; &nbsp; // just apply the spread operator (...) to `sources`&nbsp; &nbsp; // to spread its elements into the dependency array of `useEffect`&nbsp; }, [query, ...sources]);&nbsp; return response;};解释自useSearch定义挂钩传递[query, sources]到 的 dep 数组useEffect,其中 assources: string[]本身就是一个数组。这使得 dep 数组的形状为:["query", ["source_1", "source_2", ..., "source_n"]]看到 dep 数组的第二个元素是一个嵌套数组。useEffect然而,使用 dep 数组的方法是Object.is对其每个元素应用相等检查:// pseudo codefunction isDepArrayEqual(prevDepArray: any[], currDepArray: any[]) {&nbsp; return prevDepArray.every(&nbsp; &nbsp; (prevElement, index) => Object.is(prevElement, currDepArray[index])&nbsp; )}每次重新渲染时,钩子调用useSearch("Donald", ["bbc-news"])都会创建一个新的数组实例sources。这将使检查失败Object.is(prevSources, currSources),因为数组的相等性是通过它们的引用来比较的,而不是它们包含的值。使用扩展运算符[query, ...sources],您可以将 dep 数组的形状转换为:["query", "source_1", "source_2", ..., "source_n"]关键区别不在于复制,而在于解压数组sources。现在嵌套sources数组已解包,并且 dep 数组的每个元素只是字符串。对字符串的相等性检查是通过它们的值而不是引用进行比较,因此useEffect将认为 dep 数组不变。错误已修复。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript