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);
    }
}

据我所知,重新渲染时挂钩不会改变。所以问题是:

  1. 为什么每次重新渲染时 uiLoad 都会改变?使用 useWhatChanged 调试器工具,我可以发现它确实在每次重新呈现组件时都会发生变化。钩子不是每次渲染都保持不变吗?或者这不适用于自定义挂钩?

  2. 这里唯一的解决方案是使用 // 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
}