如何通过Dispatch Payload传递结构体到React Reducer?登录报错排查
问题:React登录状态更新时触发「Objects are not valid as a React child」错误
我是React新手,正在搭建Web应用的登录功能,要求用户登录后才能访问内部页面(用户数据关联操作与可见内容)。我想把user设为全局可调用的对象,登录时通过dispatch传递测试用的用户数据结构体(后续会替换为API返回数据)来更新user状态,但触发报错:
Objects are not valid as a React child (found: object with keys {esid, uuid, status...
报错提示发生在AuthProvider中,以下是相关完整代码:
App.js
export default function App() { return ( <div className="App"> <AuthProvider> <LocationsProvider> <StoriesProvider> <BrowserRouter> <Routes> <Route index element={<Login />} /> <Route path="/" element={<ProtectedRoute> <Route path="home" element={<Homepage />} /> <Route path="locations" element={<Locations />} /> <Route path="locations/:id" element={<LocationEdit />} /> <Route path="locationnew" element={<LocationNew />} /> <Route path="memories" element={<Memories />} /> <Route path="connections" element={<Connections />} /> <Route path="story" element={<Story />} /> </ProtectedRoute>} ></Route> <Route path="*" element={<PageNotFound />} /> </Routes> </BrowserRouter> </StoriesProvider> </LocationsProvider> </AuthProvider> </div>
ProtectedRoute.js
import { useEffect } from "react"; import { useNavigate } from "react-router-dom"; import { useAuth } from "../contexts/AuthContext"; function ProtectedRoute({ children }) { const { isAuthenticated } = useAuth(); const navigate = useNavigate(); useEffect( function () { if (!isAuthenticated) navigate("/"); }, [isAuthenticated, navigate] ); return isAuthenticated ? children : null; } export default ProtectedRoute;
Login.js
export default function Login() { // PRE-FILL FOR DEV PURPOSES const [email, setEmail] = useState("test@emaildomain.com"); const [password, setPassword] = useState("myfakepassword"); const { login, isAuthenticated } = useAuth(); const navigate = useNavigate(); function handleSubmit(e) { e.preventDefault(); console.log("Logging in..."); if (email && password) login(email, password); } useEffect( function () { if (isAuthenticated) navigate("/home", { replace: true }); }, [isAuthenticated] ); return ( <main className={styles.login}> <form className={styles.form} onSubmit={handleSubmit}> <div className={styles.row}> <label htmlFor="email">Email address</label> <input type="email" id="email" onChange={(e) => setEmail(e.target.value)} value={email} /> </div> <div className={styles.row}> <label htmlFor="password">Password</label> <input type="password" id="password" onChange={(e) => setPassword(e.target.value)} value={password} /> </div> <div> <Button type="primary">Login</Button> </div> </form> </main> ); }
AuthContext.js
import { createContext, useContext, useReducer } from "react"; const AuthContext = createContext(); const initialState = { user: null, isAuthenticated: false, }; function reducer(state, action) { switch (action.type) { case "login": return { ...state, user: action.payload, isAuthenticated: true }; case "logout": return { ...state, user: null, isAuthenticated: false }; default: throw new Error("Unknown action"); } } const FAKE_USER = { esid: "1", uuid: "11111111-0000-2222-3333333333333333", status: "1", firstName: "Test", lastName: "User", screenname: "TestUser01", profilepic: "avatar.jpg", email: "test@emaildomain.com", }; function AuthProvider({ children }) { const [{ user, isAuthenticated }, dispatch] = useReducer( reducer, initialState ); function login(email, password) { console.log(FAKE_USER); //API Connectivity and verification will go here... //payload is causing ERROR if (email === "test@emaildomain.com" && password === "myfakepassword") dispatch({ type: "login", payload: FAKE_USER }); } function logout() { dispatch({ type: "logout" }); } return ( <AuthContext.Provider value={{ user, isAuthenticated, login, logout }}> {children} </AuthContext.Provider> ); } function useAuth() { const context = useContext(AuthContext); if (context === undefined) throw new Error("AuthContext was used outside AuthProvider"); return context; } export { AuthProvider, useAuth };
解决方案
这个错误不是AuthProvider的问题,而是你在某个受保护页面(比如Homepage、Locations等)中直接尝试渲染user对象本身,而React无法直接渲染JavaScript对象,只能渲染字符串、数字、React元素等合法的React子节点。
1. 定位问题代码
检查所有使用useAuth()获取user的组件,看是否存在类似这样的代码:
const { user } = useAuth(); // 错误写法:直接渲染整个user对象 return <div>{user}</div>;
2. 修复示例
你需要渲染user对象的具体属性,比如:
const { user } = useAuth(); // 正确写法:渲染对象的属性 return ( <div> 欢迎回来,{user.firstName} {user.lastName} <img src={user.profilepic} alt={user.screenname} /> </div> );
如果只是想调试查看user的内容,可以用JSON.stringify:
// 仅用于调试,正式代码不建议这么做 return <div>{JSON.stringify(user)}</div>;
3. 额外提示
为了避免登录前user为null导致的报错,建议添加空值检查:
const { user } = useAuth(); return ( <div> {user?.firstName && <span>欢迎回来,{user.firstName}</span>} </div> );
内容的提问来源于stack exchange,提问作者Big Fat Designs
相关产品推荐
相关产品推荐

