useReducer - 尝试编写自己的 useReducer,如果卸载组件则不会使用分派

useReducer - Trying to write own useReducer which will not use dispatch if component is unmounted

您能否就以下代码提供反馈:

export function useUnmountSafeReducer<R extends Reducer<any, any>>(
  reducer: R,
  initialState: ReducerState<R>,
  initializer?: undefined
): [ReducerState<R>, Dispatch<ReducerAction<R>>] {
  const [mounted, setMounted] = useState(true);
  const [state, dispatch] = useReducer(reducer, initialState);

  useEffect(() => {
    return () => {
      setMounted(false);
    };
  }, []);

  return [state, mounted ? dispatch : () => {}];
}

我正在尝试编写自己的减速器,如果组件被卸载,它将不会使用分派。

尝试使用 ref 而不是状态。

  const mounted = useRef(true)

  useEffect(() => {
    return () => {
      mounted.current = false
    }
  }, [])

原因是使用setMounted是在useEffect的销毁函数中使用的内存泄漏。请记住,如果组件已卸载,您不应在此之后使用任何内部方法。实际上避免内存泄漏是您首先实现此 mounted 的原因,不是吗?

禁用调度

现在的问题是您可以 return 卸载后进行新的调度吗?

  return [state, mounted ? dispatch : () => {}]

卸载后,UI 可能不会再有任何更新。所以让它工作的方法是禁用现有的 dispatch 但不提供空的

  const _dispatch = useCallback((v) => {
    if (!mounted || !mounted.current) return
    dispatch(v)
  }, [])

  return [state, _dispatch]

那里的useCallback可能是可选的。