我试图用react钩子(Hook)构建一个redux进程,下面的代码是我想用getUsers(redux action)调用模拟一个ComponentDidMount
函数,这是一个获取数据的http请求。
第一个版本是这样的
const { state, actions } = useContext(StoreContext);
const { getUsers } = actions;
useEffect(() => {
getUsers(); // React Hook useEffect has a missing dependency: 'getUsers'.
}, []);
但我收到了警告:“React Hook useEffect具有缺少的依赖项:'getUsers'。要么包含它,要么删除依赖项数组”在useEffect中,
然后我将getUsers添加到依赖项数组,但是在那里出现无限循环
useEffect(() => {
getUsers();
}, [getUsers])
现在,我通过使用useRef找到了解决方案
const fetchData = useRef(getUsers);
useEffect(() => {
fetchData.current();
}, []);
不确定这是否是正确的方法,但是确实解决了棉绒和无限循环(暂时吗?)
我的问题是:
在第二版代码中,到底是什么导致了无限循环?每次渲染后,依赖数组中的getUsers是否会发生变化?
最佳答案
您的函数具有依赖关系,React认为不列出依赖关系是不安全的。说您的功能取决于名为users
的属性。在Dependencies数组中明确列出隐式依赖项将不起作用:
useEffect(() => {
getUsers();
}, [users]); // won't work
但是,React says that the recommended way to fix this会将函数移到
useEffect()
函数内部。这样,警告不会说它缺少getUsers
依赖项,而是getUsers
依赖的一个或多个依赖项。function Example({ users }) {
useEffect(() => {
// we moved getUsers inside useEffect
function getUsers() {
console.log(users);
}
getUsers();
}, []); // users dependency missing
}
因此,您可以指定
users
依赖项:useEffect(() => {
function getUsers() {
console.log(users);
}
getUsers();
}, [users]); // OK
但是,您是从props获得该功能的,而组件中未定义该功能。
那该怎么办呢?解决您的问题的方法是memoize您的函数。
您无法在组件中记住它,因为会出现相同的警告:
const memoizedGetUsers = useCallback(
() => {
getUsers();
},
[], // same warning, missing the getUsers dependency
);
解决方案是在定义
getUsers
的位置记住它,然后您将能够列出依赖项:// wrap getUsers inside useCallback
const getUsers = useCallback(
() => {
//getUsers' implementation using users
console.log(users);
},
[users], // OK
);
在您的组件中,您将能够执行以下操作:
const { getUsers } = actions; // the memoized version
useEffect(() => {
getUsers();
}, [getUsers]); // it is now safe to set getUsers as a dependency
至于为什么存在无限循环以及useRef起作用的原因。我猜想您的函数会导致重新渲染,并且在每次迭代中,都会重新创建getUsers,最终导致一个无限循环。 useRef返回一个对象
{ current: ... }
,而使用useRef和自己创建该对象{ current: ... }
之间的区别是useRef
返回相同的对象,而不创建另一个对象。因此,您可能使用了相同的功能。关于reactjs - 关于使用中的无限循环,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59235461/