我目前正试图找出如何避免在上下文提供程序中包装我的应用程序(从useReducer中获取值(,然后使用useEffect钩子通过子组件进行更新时创建无限循环。
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 (...)
我可能遗漏了一些显而易见的东西,但任何提示都可能帮助其他遇到同样问题的人。
CodeSandbox的完整示例。
问题的根源在于
<Route path="/page1" component={() => <Page1 />} />
当您将内联箭头函数作为组件传递时,基本上就是为每个渲染创建新的组件,并强制Route
完全重新装载此部分。当它发生时,useEffect
再次被调用,依此类推
你需要这样改变:
<Route path="/page1"><Page1 /></Route>
// or
<Route path="/page1" component={Page1} />
引用自react router文档:
当您使用组件(而不是下面的render或children(时,路由器使用React.createElement从给定组件创建一个新的React元素。这意味着,如果向组件道具提供内联函数,则每次渲染都会创建一个新组件。这将导致现有组件卸载和新组件安装,而不仅仅是更新现有组件。使用内联函数进行内联渲染时,请使用渲染或子道具(如下(。
来源:https://reactrouter.com/web/api/Route/route-render-methods