1 回答

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