React路由点击Link页面重载而非重渲染匹配组件问题
问题:React Router点击Link触发全页重载,无法实现局部渲染
我正在开发一个网站,参考路由逻辑实现后,出现点击Link组件时页面全量重载的问题——明明没有使用原生<a>标签,却无法实现仅重渲染匹配组件的效果。项目环境:react@17.0.2,react-router-dom@5.3.0。
相关代码如下:
StaffRoutes.js
var staffRoutes = [ { path: "/members", name: "Members", component: MemberContainer, layout: BaseLayout, exact: true }, { path: "/teachers", name: "Teachers", component: TeacherContainer, layout: BaseLayout, // 其他配置 } ] export default staffRoutes
路由整合文件
import React, { Component } from "react"; import { BrowserRouter as Router, Redirect, Route, Switch } from "react-router-dom"; import Login from "../views/login"; import staffRoutes from "./StaffRoutes"; const PrivateRouter = ({ component, ...options }) => { const token = sessionStorage.getItem("token"); const finalComponent = token ? ( <Route {...options} component={component} /> ) : ( <Redirect to="/login" /> ); return finalComponent; }; // 注意:这段代码应该在组件的render方法内 <Router> <Switch> {staffRoutes.map((route, key) => { return ( <PrivateRouter path={route.path} key={key} exact={route.exact} component={props => { return ( <route.layout {...props}> <route.component {...props} /> </route.layout> ); }}/>); })} <Route Redirect to="/login" exact component={Login} /> </Switch> </Router>
BaseLayout代码
// 假设这是Class组件的render内容 <div className="main-content"> <SidebarWrapper /> <div className="home-section"> <div className="home-content"> <Header /> </div> <div> {this.props.children} </div> </div> </div>
侧边栏代码
import React from "react"; import { Link } from "react-router-dom"; const Admin = () => { return ( <> <ul className="sub-menu"> <li> <Link to="/members">Members</Link> </li> <li> <Link to="/teachers">Teachers</Link> </li> <li> <Link to="/departments">Departments</Link> </li> </ul> </> ); };
我怀疑问题出在这段代码,但无法定位具体原因:
<route.layout {...props}> <route.component {...props} /> </route.layout>
问题分析
- 组件命名错误:React规定自定义组件必须以大写字母开头,你使用小写的
route.layout和route.component会被React识别为原生HTML标签,导致每次路由切换时都重新挂载整个布局组件,触发全页重载。 - PrivateRouter实现不规范:react-router-dom v5中,私有路由应该是一个返回
<Route>的组件,你的实现方式会导致路由上下文传递异常,影响客户端路由的正常工作。 - Login路由写法错误:
<Route>组件没有Redirect属性,正确的兜底跳转应该单独使用<Redirect>组件。
解决方案
1. 修正组件渲染时的命名
将route.layout和route.component转为大写开头的变量,告诉React这是自定义组件:
{staffRoutes.map((route, key) => { // 提取组件并转为大写开头 const Layout = route.layout; const Component = route.component; return ( <PrivateRouter path={route.path} key={key} exact={route.exact} component={props => { return ( <Layout {...props}> <Component {...props} /> </Layout> ); }} /> ); })}
2. 重构PrivateRouter组件
按照react-router-dom v5的规范实现私有路由:
const PrivateRouter = ({ component: Component, ...rest }) => { const token = sessionStorage.getItem("token"); return ( <Route {...rest} render={props => token ? ( <Component {...props} /> ) : ( <Redirect to={{ pathname: "/login", state: { from: props.location } }} /> ) } /> ); };
3. 修正Login路由和兜底跳转
<Router> <Switch> {/* 私有路由 */} {staffRoutes.map((route, key) => { const Layout = route.layout; const Component = route.component; return ( <PrivateRouter path={route.path} key={key} exact={route.exact} render={props => ( <Layout {...props}> <Component {...props} /> </Layout> )} /> ); })} {/* 登录路由 */} <Route path="/login" exact component={Login} /> {/* 兜底跳转至登录页 */} <Redirect to="/login" /> </Switch> </Router>
内容的提问来源于stack exchange,提问作者Apollo Vostok
相关产品推荐
相关产品推荐

