useEffect props 回调函数导致死循环
useEffect props callback function causing infinite loop
我有一个与此非常相似的问题 - 。
有一个关键区别 - 我将一个获取函数传递给子组件,以便从 useEffect 调用,所以我不能简单地将函数移动到效果主体中。每次渲染都会重新创建 fetch 函数并导致无限循环。我有其他本地组件状态,我想触发效果。
我基本上有一个容器组件和一个展示组件。 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]);
在"MyGrid"中"skip"和"sorts"可以改变,并且应该使效果火起来。
"fetchItems" is re-created everytime and causes an infinite loop. This
is my problem.
现在,eslint react-hooks/exhaustive-deps 规则让我将 fetchItems 放入依赖项列表中。我有更漂亮的设置,可以在保存时自动修复,这让情况变得更糟。
我知道 Container/Presentational 模式与钩子不合时宜,但它对我的情况很有用 - 我可能允许动态地将 MyGrid 换成 MyList,并且不想重复所有的 redux 内容每个子组件。
我尝试 useCallback and useMemo,但 eslint 只是让我将所有相同的依赖项放入它的依赖项数组参数中。
除了禁用 eslint 规则之外还有其他方法吗
// eslint-disable-next-line react-hooks/exhaustive-deps
让这个工作?
有两种方法,你可以让它工作。
首先,使用useCallback
获取像
这样的fetchItem
const fetchItems = useCallback(opts => dispatch(actions.fetchItems(opts)), [dispatch, actions]);
其次直接在子组件
中使用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]);
我有一个与此非常相似的问题 -
有一个关键区别 - 我将一个获取函数传递给子组件,以便从 useEffect 调用,所以我不能简单地将函数移动到效果主体中。每次渲染都会重新创建 fetch 函数并导致无限循环。我有其他本地组件状态,我想触发效果。
我基本上有一个容器组件和一个展示组件。 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]);
在"MyGrid"中"skip"和"sorts"可以改变,并且应该使效果火起来。
"fetchItems" is re-created everytime and causes an infinite loop. This is my problem.
现在,eslint react-hooks/exhaustive-deps 规则让我将 fetchItems 放入依赖项列表中。我有更漂亮的设置,可以在保存时自动修复,这让情况变得更糟。
我知道 Container/Presentational 模式与钩子不合时宜,但它对我的情况很有用 - 我可能允许动态地将 MyGrid 换成 MyList,并且不想重复所有的 redux 内容每个子组件。
我尝试 useCallback and useMemo,但 eslint 只是让我将所有相同的依赖项放入它的依赖项数组参数中。
除了禁用 eslint 规则之外还有其他方法吗
// eslint-disable-next-line react-hooks/exhaustive-deps
让这个工作?
有两种方法,你可以让它工作。
首先,使用useCallback
获取像
const fetchItems = useCallback(opts => dispatch(actions.fetchItems(opts)), [dispatch, actions]);
其次直接在子组件
中使用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]);