简体   繁体   English

如何在数组依赖中正确使用 useEffect 钩子。 我从 redux 商店传递了状态,但我的组件仍然无限渲染

[英]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);

Live example here .现场示例在这里

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.

相关问题 如何使用 UseEffect() Hook 从 Redux 中获取状态 - How to Use UseEffect() Hook to Fetch State from Redux React Hook useEffect 缺少依赖项。 当没有任何东西损坏时,为什么我会收到此错误? - React Hook useEffect has a missing dependency. Why am I getting this error when nothing is broken? 在 useEffect 依赖数组中使用 Redux state 时如何避免无限循环? - How do I avoid infinite loop when using Redux state in useEffect dependency array? 如何使用 useEffect 钩子和依赖列表作为对象数组中的特定字段? - How to use useEffect hook with the dependency list as a specific field in an array of objects? react props 如何合并从父组件传递的 state 和 redux 存储 - how does react props merge state passed from parent component and redux store 如何从使用该钩子的钩子更新组件中的 state 而不会导致无限重新渲染? - How can I update state in a component from a hook where that hook is used without causing infinite re-renders? 如何从 useEffect 访问组件的当前状态而不使其成为依赖项? - How to access current state of component from useEffect without making it a dependency? 如何在同一反应组件中使用本地状态以及redux存储状态? - How do I use local state along with redux store state in the same react component? 我没有正确地改变我的 redux 商店的 state - I am not properly mutate the state of my redux store 如何在相同的 useEffect 挂钩中使用 state? - how to use state in same useEffect hook?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM