React Router嵌套路由子组件无法渲染问题求助
React Router v6 嵌套路由子组件不渲染问题解决
问题描述
使用react-router-dom 6.11.2配置嵌套路由后,访问/auth/new-user时CreateUser组件无法渲染,仅Login组件内容显示;若将new-user设为/auth的同级绝对路由,组件可正常渲染。
App.js 路由配置代码
import "./App.css"; import { Route, RouterProvider, createBrowserRouter, createRoutesFromElements, } from "react-router-dom"; import RootLayout from "./layouts/RootLayout"; import { UserContextProvider } from "./store/user-context"; import NotFound404 from "./components/Utility/NotFound404"; import Login from "./pages/general/Login"; import CreateUser from "./pages/general/CreateUser"; const clientRouter = createBrowserRouter( createRoutesFromElements( <> <Route path="/auth" element={<Login />}> <Route path="new-user" element={<CreateUser />} /> </Route> <Route path="/" element={<RootLayout />} errorElement={<NotFound404 />}> {/* children routes */} </Route> </> ) ); function App() { return ( <> <UserContextProvider> <RouterProvider router={clientRouter}></RouterProvider> </UserContextProvider> </> ); } export default App;
Login 组件原代码
import React, { useState } from "react"; import { Link, useNavigate } from "react-router-dom"; import styles from "./Login.module.css"; import Title from "../../components/Layout/Title"; const Login = () => { console.log("login rendered"); const navigate = useNavigate(); const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const handleSubmit = async (event) => { event.preventDefault(); console.log("Login submitted:", email, password); try { const response = await fetch("http://localhost:8000/login", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ email, password }), }); if (response.ok) { //do something } else { //do something } } catch (error) { console.log(error); //handle error } }; return ( <> <Title /> <div className={styles.loginForm}> <h2>Login</h2> <form onSubmit={handleSubmit}> <div className={styles.formControl}> <label htmlFor="email">Email:</label> <input type="email" id="email" value={email} onChange={(e) => setEmail(e.target.value)} required /> </div> <div className={styles.formControl}> <label htmlFor="password">Password:</label> <input type="password" id="password" value={password} onChange={(e) => setPassword(e.target.value)} required /> </div> <button type="submit">Login</button> </form> <Link to="new-user">Create New User</Link> </div> </> ); }; export default Login;
问题原因
React Router v6 中,嵌套路由的子组件必须通过父路由组件中的 <Outlet /> 来挂载渲染。当前Login组件未导入并使用<Outlet />,导致子路由/auth/new-user对应的CreateUser组件没有渲染的容器位置。
解决方案
修改Login组件,导入Outlet并在合适位置添加该组件,为子路由组件提供渲染入口:
修改后的Login组件代码
import React, { useState } from "react"; import { Link, useNavigate, Outlet } from "react-router-dom"; // 新增Outlet导入 import styles from "./Login.module.css"; import Title from "../../components/Layout/Title"; const Login = () => { console.log("login rendered"); const navigate = useNavigate(); const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const handleSubmit = async (event) => { event.preventDefault(); console.log("Login submitted:", email, password); try { const response = await fetch("http://localhost:8000/login", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ email, password }), }); if (response.ok) { //do something } else { //do something } } catch (error) { console.log(error); //handle error } }; return ( <> <Title /> <div className={styles.loginForm}> <h2>Login</h2> <form onSubmit={handleSubmit}> <div className={styles.formControl}> <label htmlFor="email">Email:</label> <input type="email" id="email" value={email} onChange={(e) => setEmail(e.target.value)} required /> </div> <div className={styles.formControl}> <label htmlFor="password">Password:</label> <input type="password" id="password" value={password} onChange={(e) => setPassword(e.target.value)} required /> </div> <button type="submit">Login</button> </form> <Link to="new-user">Create New User</Link> </div> {/* 添加Outlet,子路由组件将渲染在此处 */} <Outlet /> </> ); }; export default Login;
可选优化:访问子路由时隐藏父组件内容
如果希望访问/auth/new-user时只显示CreateUser组件、隐藏Login表单,可以通过useMatch判断当前路由,控制内容显示:
import { Link, useNavigate, Outlet, useMatch } from "react-router-dom"; const Login = () => { const isNewUserRoute = useMatch("/auth/new-user"); // ...其他逻辑代码 return ( <> <Title /> {/* 仅在非new-user路由时显示Login表单 */} {!isNewUserRoute && ( <div className={styles.loginForm}> <h2>Login</h2> {/* 表单及链接代码 */} </div> )} <Outlet /> </> ); };
内容的提问来源于stack exchange,提问作者KapteinKonyn
相关产品推荐
相关产品推荐

