Suspense/Await加载数据存入state后触发无限循环问题求助
解决Await组件中dispatch触发无限循环的问题
问题根源
你当前的代码会触发无限循环,核心原因是在Await的回调函数里直接调用dispatch:组件每次渲染时,这个回调都会执行;dispatch更新状态后会触发组件重新渲染,重新渲染又会再次执行dispatch,形成死循环。
解决方案
方法一:用useEffect监听loaderData变化(推荐)
利用useEffect的依赖机制,仅当loaderData发生变化时才执行dispatch,避免重复触发:
const { loaderData } = useLoaderData(); const [displayState, dispatchDisplayState] = useReducer(/* 你的reducer逻辑 */); // 监听loaderData,数据更新时才执行状态同步 useEffect(() => { if (loaderData) { dispatchDisplayState({ type: "LOAD_DATA", data: { loaderData } }); } }, [loaderData, dispatchDisplayState]); // 依赖项包含loaderData和dispatch return ( <Suspense fallback={<p style={{ textAlign: 'center', fontWeight:'bold' }}>Loading...</p>}> <Await resolve={loaderData}> {(resolvedData) => <PostList {...resolvedData} />} </Await> </Suspense> );
这种方式能正确响应loaderData的所有变化(比如数据重新加载、更新的场景),符合React的状态管理逻辑。
方法二:用useRef标记是否已执行dispatch
如果只需要在第一次获取到数据时同步状态,可以用useRef记录执行状态:
const { loaderData } = useLoaderData(); const [displayState, dispatchDisplayState] = useReducer(/* 你的reducer逻辑 */); const hasDispatched = useRef(false); return ( <Suspense fallback={<p style={{ textAlign: 'center', fontWeight:'bold' }}>Loading...</p>}> <Await resolve={loaderData}> {(resolvedData) => { // 仅第一次获取数据时执行dispatch if (!hasDispatched.current) { dispatchDisplayState({ type: "LOAD_DATA", data: { loaderData: resolvedData } }); hasDispatched.current = true; } return <PostList {...resolvedData} />; }} </Await> </Suspense> );
useRef的current值不会随组件渲染重置,标记为true后就不会再触发dispatch。
内容的提问来源于stack exchange,提问作者D. Rattansingh
相关产品推荐
相关产品推荐

