React Router:点击Link后URL变更但视图未更新的问题
问题:React Router点击Link后URL变化但页面不渲染对应组件
问题场景
我在App.js里配置了顶层路由:
import React, { Component } from 'react'; import './App.css'; import PdfViewer from './components/PdfViewer'; import {BrowserRouter as Router, Link, Switch, Route} from 'react-router-dom' import history from './history'; import Homepage from './components/Homepage' class App extends Component { render() { return ( <Router history={history}> <Switch> <Route exact path="/" component={Homepage} /> <Route path="/pdfviewer" component={PdfViewer} /> </Switch> </Router> ); } }
然后在嵌套组件MainListItems里写了Link:
import React from 'react'; import ListItem from '@material-ui/core/ListItem'; import ListItemIcon from '@material-ui/core/ListItemIcon'; import ListItemText from '@material-ui/core/ListItemText'; import DashboardIcon from '@material-ui/icons/Dashboard'; import { BrowserRouter as Router, Link } from "react-router-dom"; export const MainListItems = () => { return( <Link to="/"> <div> <ListItem button> <ListItemIcon> <DashboardIcon /> </ListItemIcon> <ListItemText primary="Dashboard" /> </ListItem> </div> </Link> )}
点击这个Link时,URL确实变成了/,但页面并没有渲染Homepage组件,这是为什么?
问题原因
这是个React Router新手常踩的坑:你在嵌套组件里重复引入了BrowserRouter,导致出现了多层路由上下文冲突。
顶层的App.js已经用<Router>(也就是BrowserRouter)把整个应用包裹起来了,所有路由相关的逻辑都应该在这个顶层路由上下文里运行。但你在MainListItems里又导入了BrowserRouter,虽然没直接写<Router>标签,但这个组件里的Link会默认绑定到当前模块导入的路由上下文,而不是顶层的那个。
结果就是:点击Link后,内部的路由上下文更新了URL,但顶层的路由完全没感知到这个变化,自然不会触发路由匹配和组件渲染。
解决方案
只需要去掉嵌套组件里的BrowserRouter导入,保留Link即可——因为整个应用已经在顶层Router的上下文覆盖下,所有子组件里的路由相关元素都会自动共享这个上下文。
修改后的MainListItems代码:
import React from 'react'; import ListItem from '@material-ui/core/ListItem'; import ListItemIcon from '@material-ui/core/ListItemIcon'; import ListItemText from '@material-ui/core/ListItemText'; import DashboardIcon from '@material-ui/icons/Dashboard'; // 只保留Link的导入,去掉BrowserRouter import { Link } from "react-router-dom"; export const MainListItems = () => { return( <Link to="/"> <div> <ListItem button> <ListItemIcon> <DashboardIcon /> </ListItemIcon> <ListItemText primary="Dashboard" /> </ListItem> </div> </Link> )}
这里也提醒下:React Router的核心原则是整个应用只需要一个Router实例,所有Route、Link、Switch这类组件都必须放在这个唯一的Router内部,避免多层路由上下文冲突。
内容的提问来源于stack exchange,提问作者Kristoffer Tølbøll
相关产品推荐
相关产品推荐

