[英]How to use useEffect hook properly with array dependency. I passed state from redux store and still my component renders infinitely
I am using useEffect hook and getting a list of users data with fetch call using function getStoreUsers which dispatches an action on response and stores shopUsers (which is an array) inside the redux store.我正在使用 useEffect 钩子并使用函数getStoreUsers获取带有 fetch 调用的用户数据列表,该函数在响应上调度操作并将shopUsers (这是一个数组)存储在 redux 存储中。
In array dependency, I am writing [shopUsers] .在数组依赖中,我正在编写[shopUsers] 。 I don't know why it is causing infinite rendering.
我不知道为什么它会导致无限渲染。
Here is how I am using useEffect hook:这是我如何使用 useEffect 钩子:
useEffect(() => {
const { getStoreUsers, shopUsers } = props;
setLoading(true);
getStoreUsers().then(() => {
setLoading(false);
}).catch(() => {
setLoading(false);
});
}, [shopUsers]);
I want to re-render component only when data inside shopUsers array changes.我只想在 shopUsers 数组中的数据发生更改时重新渲染组件。
If I write shopUsers.length inside array dependency.如果我在数组依赖项中写入 shopUsers.length。 It stops to re-render.
它停止重新渲染。
But, let's suppose I have have a page which opens up when the user clicks on a userList and updates user data on next page.但是,假设我有一个页面,当用户单击 userList 并在下一页更新用户数据时,该页面会打开。 After the update I want the user to go back to the same component which is not unmounted previously.
更新后,我希望用户返回到以前未卸载的相同组件。 So, In this case array length remains the same, but data inside in of array index is updated.
因此,在这种情况下,数组长度保持不变,但更新了数组索引中的数据。 So shopUsers.length won't work in that case.
所以 shopUsers.length 在这种情况下不起作用。
You can make a custom hook to do what you want:您可以制作自定义挂钩来执行您想要的操作:
In this example, we replace the last element in the array, and see the output in the console.在此示例中,我们替换数组中的最后一个元素,并在控制台中查看输出。
import React, { useState, useEffect, useRef } from "react";
import ReactDOM from "react-dom";
import { isEqual } from "lodash";
const usePrevious = value => {
const ref = useRef();
useEffect(() => {
ref.current = value;
});
return ref.current;
};
const App = () => {
const [arr, setArr] = useState([2, 4, 5]);
const prevArr = usePrevious(arr);
useEffect(() => {
if (!isEqual(arr, prevArr)) {
console.log(`array changed from ${prevArr} to ${arr}`);
}
}, [prevArr]);
const change = () => {
const temp = [...arr];
temp.pop();
temp.push(6);
setArr(temp);
};
return (
<button onClick={change}>change last array element</button>
)
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Your effect is triggered based on the "shopUsers" prop, which itself triggers a redux action that updates the "shopUsers" prop and thats why it keeps infinitely firing.您的效果是基于“shopUsers”道具触发的,它本身会触发一个 redux 操作来更新“shopUsers”道具,这就是它无限触发的原因。
I think what you want to optimize is the rendering of your component itself, since you're already using redux, I'm assuming your props/state are immutable, so you can use React.memo
to re-render your component only when one of its props change.我认为你想要优化的是组件本身的渲染,因为你已经在使用 redux,我假设你的 props/state 是不可变的,所以你可以使用
React.memo
重新渲染你的组件其道具变化。
Also you should define your state/props variable outside of your hooks since they're used in the scope of the entire function like so.此外,您应该在钩子之外定义 state/props 变量,因为它们像这样在整个函数的范围内使用。
In your case, if you pass an empty array as a second param to memo, then it will only fire on ComponentDidMount, if you pass null/undefined or dont pass anything, it will be fired on ComponentDidMount + ComponentDidUpdate, if you want to optimise it that even when props change/component updates the hook doesn't fire unless a specific variable changes then you can add some variable as your second argument在你的情况下,如果你将一个空数组作为第二个参数传递给备忘录,那么它只会在 ComponentDidMount 上触发,如果你传递 null/undefined 或不传递任何东西,它将在 ComponentDidMount + ComponentDidUpdate 上触发,如果你想优化即使道具更改/组件更新,钩子也不会触发,除非特定变量发生更改,然后您可以添加一些变量作为第二个参数
React.memo(function(props){
const [isLoading, setLoading] = useState(false);
const { getStoreUsers, shopUsers } = props;
useEffect(() => {
setLoading(true);
getStoreUsers().then(() => {
setLoading(false);
}).catch((err) => {
setLoading(false);
});
}, []);
...
})
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.