React useState与useLoaderData联用触发无限循环问题求助
问题分析与解决方案
无限循环原因
- 渲染阶段直接修改State:你在组件渲染逻辑(函数体同步执行代码)里调用
setUser,每次组件渲染时,只要auth.success为true就会触发State更新,进而导致组件重新渲染,再次执行这段代码,形成无限循环。React组件渲染时,函数体代码会同步执行,直接在此处调用setState必然引发重渲染循环。 - Loader未解析响应:你的
authLoader直接返回了fetch的Response对象,并未解析为JSON数据,因此auth.success实际不存在(Response对象无此属性),这也会导致逻辑异常。
修复步骤
1. 修复AuthLoader,解析API响应
修改AuthLoader.js,将Response解析为JSON格式:
import { API_HOST } from "../config" const authLoader = async () => { const res = await fetch(`${API_HOST}/auth/me`, { credentials: 'include' }); // 解析响应为JSON结构 return await res.json(); } export default authLoader
2. 避免渲染阶段直接调用setUser
两种可行方案:
方案一:用useEffect监听loader数据变化
在root.jsx中通过useEffect,仅当auth数据变化时更新State:
import { useState, useEffect } from "react" import { Outlet, useLoaderData } from "react-router-dom" import { UserContext } from "../../context/UserContext" const Home = () => { const [user, setUser] = useState() const auth = useLoaderData() useEffect(() => { if (auth.success) { setUser(auth.data.user) } }, [auth]) // 依赖auth,仅当auth变化时执行 return ( <UserContext.Provider value={{user, setUser}}> <Outlet/> </UserContext.Provider> ) } export default Home
方案二:直接用loader数据作为初始State
如果用户数据无需后续本地修改,可直接将loader返回的数据作为State初始值:
import { useState } from "react" import { Outlet, useLoaderData } from "react-router-dom" import { UserContext } from "../../context/UserContext" const Home = () => { const auth = useLoaderData() // 用loader数据初始化user State const [user, setUser] = useState(auth.success ? auth.data.user : undefined) return ( <UserContext.Provider value={{user, setUser}}> <Outlet/> </UserContext.Provider> ) } export default Home
额外说明
React Router V6的loader数据是组件渲染前就已获取的初始化数据,优先通过初始State或useEffect处理,切勿在渲染阶段直接修改State,这是React核心规范,否则必然引发重渲染循环。
内容的提问来源于stack exchange,提问作者noahshz
相关产品推荐
相关产品推荐

