如何使用 React 的 useReducer、useContext 和 useEffect 防止死循环

How to prevent infinite loop with React's useReducer, useContext and useEffect

我目前正在尝试弄清楚如何在将我的应用程序包装在上下文提供程序中(从 useReducer 获取值)然后使用 useEffect 挂钩通过 child 组件进行更新时避免创建无限循环。

有一个问题的例子 here on CodeSandbox

显然这里不转贴所有代码很难说出问题,但是关键点:

根目录:

function App() {
   const [state, dispatch] = useReducer(reducer, initialState);
   const value = { state, dispatch };

  return (
<Context.Provider value={value}>
...
</Context.Provider>

Child:

export const Page1: FC = () => {
  const { dispatch, state } = useContext(Context);
  const { isLoading } = state;

  useEffect(() => {
    dispatch({
      type: "loading",
      payload: false
    });
  }, [dispatch]);

 return (...)

我可能遗漏了一些明显的东西,但任何指示都可能会帮助 运行 遇到同样问题的其他人。

Full example on CodeSandbox.

问题的根源在这里

<Route path="/page1" component={() => <Page1 />} />

当您将内联箭头函数作为组件传递时,您基本上会为每个渲染创建新组件并强制 Route 完全重新安装此部分。当它发生时 useEffect 被再次调用,依此类推。

你需要这样改:

<Route path="/page1"><Page1 /></Route>
// or
<Route path="/page1" component={Page1} />

来自 react-router 文档的引用:

When you use component (instead of render or children, below) the router uses React.createElement to create a new React element from the given component. That means if you provide an inline function to the component prop, you would create a new component every render. This results in the existing component unmounting and the new component mounting instead of just updating the existing component. When using an inline function for inline rendering, use the render or the children prop (below).

来源:https://reactrouter.com/web/api/Route/route-render-methods