React Router项目中点击浏览器后退按钮Div仍不可见的问题
问题:浏览器后退后Main组件内容无法自动恢复显示
我在App.jsx中使用react-router,将Main作为父组件配置嵌套路由,子路由对应Login和SignUp组件。为解决<Outlet>内容与Main组件原有内容重叠的问题,我在Main.jsx中给登录、注册按钮绑定了handleClick函数,通过useState控制为标题和按钮区域的div添加invisible类(设置display:none),隐藏这些区域以仅显示<Outlet>内容。但点击浏览器后退按钮回到根路由"/"时,这些隐藏的div依然处于不可见状态,必须刷新页面才能恢复显示。
相关代码
App.jsx
import React, { useState } from "react"; import Main from "./Main"; import SignUp from "./SignUp"; import Login from "./Login"; import Home from "./Home"; import { createBrowserRouter, createRoutesFromElements, Route, RouterProvider,} from "react-router-dom"; const router = createBrowserRouter( createRoutesFromElements( <Route path="/" element={<Main />}> <Route path="login" element={<Login />} /> <Route path="signup" element={<SignUp />} /> </Route> ) ); function App() { return <RouterProvider router={router} />; } export default App;
Main.jsx
import React, { useState } from "react"; import Button from "./Button"; import { NavLink, Outlet } from "react-router-dom"; function Main() { const [isVisible, setIsVisible] = useState(true); const handleClick = () => { setIsVisible(false); }; return ( <div className="main-div"> <div className={`main-heading-div ${isVisible ? "" : "invisible"}`}> <p className="main-heading"> Welcome to <span>The Book Keeper</span> </p> <p>Your Personal Library, Perfectly Organized</p> </div> <div className={`button-div ${isVisible ? "" : "invisible"}`}> <NavLink to="/login"> <Button text="Log in" name="main-login" onClick={handleClick} /> </NavLink> <NavLink to="/signup"> <Button text="Sign Up" name="main-signup" onClick={handleClick} /> </NavLink> </div> <Outlet /> </div> ); } export default Main;
解决方案
问题根源在于useState的状态不会随着路由后退自动重置,组件未重新渲染时状态会保持之前的false值。推荐以下两种解决方式:
方式一:监听路由变化重置状态
通过useLocation获取当前路由,用useEffect监听路径变化,当回到根路由时恢复显示状态:
import React, { useState, useEffect } from "react"; import Button from "./Button"; import { NavLink, Outlet, useLocation } from "react-router-dom"; function Main() { const [isVisible, setIsVisible] = useState(true); const location = useLocation(); useEffect(() => { // 路由回到根路径时,恢复显示状态 if (location.pathname === "/") { setIsVisible(true); } }, [location.pathname]); const handleClick = () => { setIsVisible(false); }; return ( <div className="main-div"> <div className={`main-heading-div ${isVisible ? "" : "invisible"}`}> <p className="main-heading"> Welcome to <span>The Book Keeper</span> </p> <p>Your Personal Library, Perfectly Organized</p> </div> <div className={`button-div ${isVisible ? "" : "invisible"}`}> <NavLink to="/login"> <Button text="Log in" name="main-login" onClick={handleClick} /> </NavLink> <NavLink to="/signup"> <Button text="Sign Up" name="main-signup" onClick={handleClick} /> </NavLink> </div> <Outlet /> </div> ); } export default Main;
方式二:直接根据路由路径判断显示状态
无需额外维护useState,直接通过当前路由路径决定是否显示内容,更符合react-router的设计逻辑:
import React from "react"; import Button from "./Button"; import { NavLink, Outlet, useLocation } from "react-router-dom"; function Main() { const location = useLocation(); // 仅在根路径时显示标题和按钮区域 const isVisible = location.pathname === "/"; return ( <div className="main-div"> <div className={`main-heading-div ${isVisible ? "" : "invisible"}`}> <p className="main-heading"> Welcome to <span>The Book Keeper</span> </p> <p>Your Personal Library, Perfectly Organized</p> </div> <div className={`button-div ${isVisible ? "" : "invisible"}`}> <NavLink to="/login"> <Button text="Log in" name="main-login" /> </NavLink> <NavLink to="/signup"> <Button text="Sign Up" name="main-signup" /> </NavLink> </div> <Outlet /> </div> ); } export default Main;
这种方式下,路由变化时组件会自动根据路径更新显示状态,无需手动处理点击事件和状态重置,彻底避免了状态不同步的问题。
内容的提问来源于stack exchange,提问作者Nayan Kadhre
相关产品推荐
相关产品推荐

