简体   繁体   English

useEffect道具回调函数导致无限循环

[英]useEffect props callback function causing infinite loop

I have a problem very similar to this - How do I fix missing dependency in React Hook useEffect . 我有一个与此非常相似的问题 - 如何修复React Hook useEffect中缺少的依赖项

There is one key difference - I am passing a fetch function to a child component to be called from useEffect , so I can't simply move the function into the body of the effect. 有一个关键区别 - 我将一个fetch函数传递给要从useEffect调用的子组件,所以我不能简单地将该函数移动到效果体中。 The fetch function is re-created every render and causes an infinite loop. 每次渲染都会重新创建fetch函数,并导致无限循环。 I have other local component state that I want to cause the effect to fire. 我有其他本地组件状态,我想导致效果触发。

I basically have a Container Component and a Presentational component. 我基本上有一个容器组件和一个演示组件。 MyPage is the parent of MyGrid and sets up all the redux state: MyPage是MyGrid的父级,并设置所有redux状态:

const MyPage = () => {

  const dispatch = useDispatch();
  const items= useSelector(selectors.getItems);
  const fetching = useSelector(selectors.getFetching);
  const fetchItems = opts => dispatch(actions.fetchItems(opts));

  return (
    <>
      {fetching && <div>Loading...</div>}
      <h1>Items</h1>
      <MyGrid
        items={items}
        fetchItems={fetchItems}
        fetching={fetching}
      />
    </>
  );

}

const MyGrid = ({ fetchItems, items, fetching }) => {

  const [skip, setSkip] = useState(0);
  const take = 100;
  const [sorts, setSorts] = useState([]);

  // when query opts change, get data
  useEffect(() => {

    const options = { skip, take };
    const sortString = getSortString(sorts);
    if (sortString) options['sort'] = sortString;
    fetchItems(options);

  }, [fetchItems, skip, sorts]);

In "MyGrid" "skip" and "sorts" can change, and should make the effect fire. 在“MyGrid”中,“跳过”和“排序”可以改变,并且应该使效果起火。

"fetchItems" is re-created everytime and causes an infinite loop. 每次都会重新创建“fetchItems”并导致无限循环。 This is my problem. 这是我的问题。

Now, the eslint react-hooks/exhaustive-deps rule is making me put fetchItems in the dependency list. 现在,eslint react-hooks / exhaustive-deps规则让我把fetchItem放在依赖列表中。 I have prettier setup to autofix on save which makes it worse. 我有更漂亮的设置自动修复保存,这使它变得更糟。

I know the Container/Presentational pattern is out of style with hooks, but it works good for my situation - I may allow swapping out MyGrid for MyList dynamically and don't want to repeat all the redux stuff in each child component. 我知道容器/演示模式与钩子不合适,但它适用于我的情况 - 我可能允许动态地交换MyGrid for MyList并且不想重复每个子组件中的所有redux内容。

I tried to useCallback and useMemo , but eslint just makes me put all the same dependencies in it's dependency array parameter. 我尝试使用CallbackuseMemo ,但是eslint只是让我把所有相同的依赖项放在它的依赖数组参数中。

Is there a way other than disabling the eslint rule 除了禁用eslint规则之外还有其他方法吗?

// eslint-disable-next-line react-hooks/exhaustive-deps

to make this work? 使这项工作?

There are two ways, you can make it work. 有两种方法,你可以使它工作。

Firstly , using useCallback for fetchItem like 首先 ,将useCallback用于fetchItem之类的

const fetchItems = useCallback(opts => dispatch(actions.fetchItems(opts)), [dispatch, actions]);

Secondly using dispatch directly in child component 其次直接在子组件中使用dispatch

const dispatch = useDispatch();
 useEffect(() => {

    const options = { skip, take };
    const sortString = getSortString(sorts);
    if (sortString) options['sort'] = sortString;
    dispatch(actions.fetchItems(options));

  }, [dispatch, actions, skip, sorts]);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM