如何使用React的useReducer,useContext和useEffect防止无限循环

时间:2020-07-08 22:13:14

标签: reactjs react-hooks use-effect use-reducer use-context

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

有一个问题here on CodeSandbox的例子。

很明显,要在不重新发布所有代码的情况下谈论这个问题是很困难的,但是要点:

根:

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

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

孩子:

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

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

 return (...)

我可能缺少明显的东西,但是任何指针都可以帮助遇到相同问题的其他人。

Full example on CodeSandbox

1 个答案:

答案 0 :(得分:2)

问题的根源在这里

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

当您将嵌入式箭头功能作为组件传递时,基本上是为每个渲染创建新组件,并强制Route完全重新安装此零件。发生这种情况时,useEffect会再次被调用,依此类推。

您需要像这样更改它:

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

react-router文档的引用:

当您使用组件(而不是下面的渲染器或子组件)时,路由器会使用React.createElement从给定的组件中创建一个新的React元素。这意味着,如果您向组件prop提供内联函数,则将在每个渲染中创建一个新组件。这将导致现有组件的卸载和新组件的安装,而不仅仅是更新现有组件。当使用内联函数进行内联渲染时,请使用render或children道具(如下)。

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