React Custom Hooks 和 useEffect 无限重新渲染
React Custom Hooks and useEffect infinite re-renders
export const useMyCustomHook = () => {
const uiLoad = useUiLoad(false);
useEffect(() => {
// ...
}, [...]);
}
uiLoad
是自定义挂钩(显然,useMyCustomHook
也是如此)。这工作正常 if 我没有将 uiLoad
添加到 useEffect
依赖项数组。如果我确实包含它,它会无限地重新渲染。
这是我的 uiLoad
挂钩代码:
const baseDispatch = {
type: SET_LOADING
}
export const useUiLoad = (initial: boolean = false) => {
const dispatch = useDispatch<Dispatch<UIAction>>();
const loaded = useRef(false);
useEffect(() => {
if (initial && !loaded.current) {
console.log('Called');
dispatch({
type: SET_LOADING,
loadbarShowing: true
});
loaded.current= true;
}
}, [dispatch, initial])
return (loading: boolean) => {
const data: UIAction = {
...baseDispatch,
loadbarShowing: loading
}
dispatch(data);
}
}
据我所知,重新渲染时挂钩不会改变。所以问题是:
为什么每次重新渲染时 uiLoad 都会改变?使用 useWhatChanged
调试器工具,我可以发现它确实在每次重新呈现组件时都会发生变化。钩子不是每次渲染都保持不变吗?或者这不适用于自定义挂钩?
这里唯一的解决方案是使用 // eslint-disable-next-line
抑制警告吗?
每次渲染组件时都会调用挂钩。 useUiLoad
return 每次调用时都是一个 new 函数。您可以 return 一个记忆函数,这样它就是一个稳定的参考。
export const useUiLoad = (initial: boolean = false) => {
const dispatch = useDispatch<Dispatch<UIAction>>();
const loaded = useRef(false);
useEffect(() => {
if (initial && !loaded.current) {
console.log('Called');
dispatch({
type: SET_LOADING,
loadbarShowing: true
});
loaded.current= true;
}
}, [dispatch, initial]);
return useCallback((loading: boolean) => {
const data: UIAction = {
...baseDispatch,
loadbarShowing: loading
}
dispatch(data);
}, [dispatch]); // <-- add any other dependencies if necessary
}
export const useMyCustomHook = () => {
const uiLoad = useUiLoad(false);
useEffect(() => {
// ...
}, [...]);
}
uiLoad
是自定义挂钩(显然,useMyCustomHook
也是如此)。这工作正常 if 我没有将 uiLoad
添加到 useEffect
依赖项数组。如果我确实包含它,它会无限地重新渲染。
这是我的 uiLoad
挂钩代码:
const baseDispatch = {
type: SET_LOADING
}
export const useUiLoad = (initial: boolean = false) => {
const dispatch = useDispatch<Dispatch<UIAction>>();
const loaded = useRef(false);
useEffect(() => {
if (initial && !loaded.current) {
console.log('Called');
dispatch({
type: SET_LOADING,
loadbarShowing: true
});
loaded.current= true;
}
}, [dispatch, initial])
return (loading: boolean) => {
const data: UIAction = {
...baseDispatch,
loadbarShowing: loading
}
dispatch(data);
}
}
据我所知,重新渲染时挂钩不会改变。所以问题是:
为什么每次重新渲染时 uiLoad 都会改变?使用
useWhatChanged
调试器工具,我可以发现它确实在每次重新呈现组件时都会发生变化。钩子不是每次渲染都保持不变吗?或者这不适用于自定义挂钩?这里唯一的解决方案是使用
// eslint-disable-next-line
抑制警告吗?
每次渲染组件时都会调用挂钩。 useUiLoad
return 每次调用时都是一个 new 函数。您可以 return 一个记忆函数,这样它就是一个稳定的参考。
export const useUiLoad = (initial: boolean = false) => {
const dispatch = useDispatch<Dispatch<UIAction>>();
const loaded = useRef(false);
useEffect(() => {
if (initial && !loaded.current) {
console.log('Called');
dispatch({
type: SET_LOADING,
loadbarShowing: true
});
loaded.current= true;
}
}, [dispatch, initial]);
return useCallback((loading: boolean) => {
const data: UIAction = {
...baseDispatch,
loadbarShowing: loading
}
dispatch(data);
}, [dispatch]); // <-- add any other dependencies if necessary
}