我正在制作一个React App,并且收到了这个警告。当组件安装时,我试图进行两个API调用:
useEffect(() => {
getWebsites();
loadUserRatings();
}, []);
这就是为什么我有一个空数组的原因,因为我想在安装组件时只调用一次。但是我仍然收到警告,该如何解决?
使用react redux的connect将这两个函数传递给组件,整个组件如下所示:
const Wrapper = (props) => {
const { getWebsites, loadUserRatings } = props;
useEffect(() => {
getWebsites();
loadUserRatings();
}, []);
return (
<>
<Header />
<Websites />
<Sync />
</>
);
};
答案 0 :(得分:6)
由于您很可能不会在运行时修改函数定义,因此可以将getWebsites
,loadUserRatings
添加到依赖项数组。
useEffect(() => {
getWebsites();
loadUserRatings();
}, [getWebsites, loadUserRatings]);
请注意,useEffect
,getWebsites
发生更改时,loadUserRatings
中的代码将运行。如果没有正确记住这两个功能,则会发生这种情况。
防止这种情况的一种好方法是使用useCallback
钩子在父组件中对其进行记忆,然后将其传递给Wrapper
组件。
答案 1 :(得分:1)
以我的经验,通常不会像这样通过props
传递未存储的功能。
// don't do this
<Wrapper
getWebsites={() => fetchJson('websites').then(setWebsites)}
loadUserRatings={() => fetchJson('ratings').then(setUserRatings)}
/>
如果正确地记住了它们(使用像useCallback()
这样的钩子,或者通过在任何组件之外定义),则可以安全地将它们传递到deps
的{{1}}行为上的任何差异。这是解决上述情况的示例。*
useEffect()
* // do this
const fetchJson = (...args) => fetch(...args).then(res => res.json());
const Parent = () => {
const [websites, setWebsites] = useState([]);
const [userRatings, setUserRatings] = useState({});
// useCallback creates a memoized reference
const getWebsites = useCallback(
() => fetchJson('websites').then(setWebsites),
[setWebsites]
);
const loadUserRatings = useCallback(
() => fetchJson('ratings').then(setUserRatings),
[setUserRatings]
);
...
<Wrapper
getWebsites={getWebsites}
loadUserRatings={loadUserRatings}
/>
在其返回值中记住分派函数,因此从技术上讲,将useState()
作为[]
传递给此处的每个deps
是安全的,但我相信将调度功能指定为依赖项可以通过明确传达作者的意图来提高清晰度,并且传递它们也没有任何缺点。
Ramesh's answer对于这种情况就足够了。
如果发现遇到第一种情况,则作为最后的选择,可以像这样将useCallback()
初始化为组件的状态。
props
答案 2 :(得分:1)
您必须将getWebsites
和loadUserRatings
添加到useEffect
的依赖项中:
useEffect(() => {
getWebsites();
loadUserRatings();
}, [getWebsites, loadUserRatings]
需要添加在useEffect
钩子外部定义的所有变量,并规定必须在组件主体或自定义钩子中定义它们,这些useEffect()是从参数调用或从参数传递的。无需在组件或自定义钩子外部定义的变量就可以添加到依赖项列表中。 (memoization)这是鲜为人知的rules of hooks之一。
注意:(这对您的情况不起作用,因为您的函数是通过props传递的)您也可以将函数包装在useCallback
钩子中,或在{{1}内定义所需的变量}如果不想将其自身添加到useEffect
钩子的依赖项中,则将其自身钩住。