这篇文章是为了分享一些关于React-Router中不太注意的细节。
整体写法
import React from "react";
import {
BrowserRouter as Router,
Switch,
Route,
Link
} from "react-router-dom";
export default function App() {
return (
<Router>
<div>
<nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/users">Users</Link>
</li>
</ul>
</nav>
{/* A <Switch> looks through its children <Route>s and
renders the first one that matches the current URL. */}
<Switch>
<Route exact path="/about">
<About />
</Route>
<Route exact path="/users">
<Users />
</Route>
<Route path="/">
<Home />
</Route>
</Switch>
</div>
</Router>
);
}
function Home() {
return <h2>Home</h2>;
}
function About() {
return <h2>About</h2>;
}
function Users() {
return <h2>Users</h2>;
}
我们来看几个重点:
- Router一个项目里只能有一个
- Switch的第一个Route是作为默认的Route
- 一般Link和Switch都在一个div里面
易错点
这里的易错点是我在设置一个route的child route的时候发现的。在demo中我用user来作为parent route。
首先,现在的React-Router比较喜欢我们分开来处理parent route和child route。而不是把他们都写在一块。
因此我们可以这样写
function Users() {
let { path, url } = useRouteMatch();
return (
<div>
<h2>Users</h2>
<ul>
<li>
<Link to="/users/rendering">Rendering with React</Link>
</li>
<li>
<Link to={`${url}/components`}>Components</Link>
</li>
<li>
<Link to={`${url}/props-v-state`}>Props v. State</Link>
</li>
</ul>
<Switch>
<Route exact path={path}>
<h3>Please select a topic.</h3>
</Route>
<Route path={`${path}/:topicId`}>
<h2>{topicId}
</Route>
</Switch>
</div>
}
这样我们就可以在User函数里面创建child route。但其实这样的话是无法正常显示出user的child route的,原因就在于我们把parent route的path设置成了exact。
因此我们需要把APP函数里面的<Route exact path="/users">
改成<Route path="/users">
关于问题发生的原因exact的介绍
exact是Route下的一条属性,一般而言,react路由会匹配所有匹配到的路由组件,exact能够使得路由的匹配更严格一些。
exact的值为bool型,为true是表示严格匹配,为false时为正常匹配。
如在exact为true时,/link
与/
是不匹配的,但是在false的情况下它们又是匹配的。
一个常用的场景是这样的:
<Route path='/' component={Home} />
<Route path='/page' component={Page}>
//这种情况下,page页面永远展示的是Home组件。
所以我们经常添加exact来解决上述问题。
<Route exact path='/' component={Home} />
<Route path='/page' component={Page} />
出现上面的问题的原因是,路由在匹配的时候,比如我们现在访问/page
,/
根目录是/page
的子集, 所以导致匹配成功,也就是说,没有设置严格匹配,也就是exact = { true }
的情况下,路由的子集也是符合匹配要求的。
接下来我们回到我们最开始的问题,那个问题的答案是:使用嵌套路由在父级不能用exact
因为当你匹配路由时路径加了子路由,导致父级路由路径不匹配从而父子组件都显示不了。
例如这个/users
使用了exact,当路径变为/users/rendering
时是匹配不到/users
的,这样的话就无法渲染到/users
,因此也不会渲染到/users
的子路由/users/rendering
了。