React Router v6 是 React Router 库的最新版本。与之前版本不同的是,它引入了 element 属性用于渲染路由组件,同时取消了高阶组件 withRouter。本文首先介绍了 React Router v5 中使用 withRouter 来访问 history 对象实现路由跳转的方式,然后介绍了 React Router v6 中使用 useNavigate 钩子实现路由跳转的方法。最后,本文介绍了如何使用 element 属性来渲染路由组件,并简单概述了 React Router v6 的使用流程,包括创建路由器、定义路由、渲染路由组件等步骤。
React Router v6不再需要高阶组件
React Router v6中,以下钩子函数可以替代v5中的withRouter高阶函数:
useNavigate- 替代了withRouter中的history对象,并且不需要将props传递到子组件中。useParams- 替代了withRouter中的match.params,用于获取URL中的参数。useLocation- 替代了withRouter中的location对象,用于获取当前的URL地址。useMatch- 替代了withRouter中的match对象,用于获取与URL地址匹配的路由信息。
使用这些钩子函数可以更方便地在React组件中获取React Router中的路由信息,而无需使用withRouter高阶函数。
接下来以跳转操作举例,在 React Router v5 中,只有在路由组件(即被 <Route> 包裹的组件)中才可以直接访问 history 对象。如果较里层的组件需要进行路由跳转操作,就需要通过某种方式获取到 history 对象,例如使用高阶组件 withRouter。
withRouter 是一个高阶组件,它将路由组件的 match、location 和 history 三个对象作为属性传递给被包裹的组件。使用 withRouter 将一个组件包裹后,该组件就可以通过 props 访问到 history 对象,从而进行路由跳转操作。
下面是一个使用 withRouter 的示例:
import React from 'react';
import { withRouter } from 'react-router-dom';
class MyComponent extends React.Component {
handleClick = () => {
// 使用 this.props.history.push 进行路由跳转
this.props.history.push('/some/path');
};
render() {
return <button onClick={this.handleClick}>跳转到 /some/path</button>;
}
}
// 使用 withRouter 包裹 MyComponent,使其可以访问到 history 对象
export default withRouter(MyComponent);
在上面的示例中,我们定义了一个名为 MyComponent 的组件,并在其中定义了一个点击事件处理函数 handleClick,在该函数中通过 this.props.history.push 进行路由跳转操作。然后,我们使用 withRouter 将 MyComponent 组件包裹,并导出包裹后的组件。这样,我们就可以在任意位置使用被包裹后的组件,并访问到 history 对象了。
需要注意的是,使用 withRouter 包裹组件可能会影响到性能,因为每次路由变化时都会触发重新渲染。因此,在使用 withRouter 时应该注意组件的性能优化。
而在 React Router v6 中,可以使用 useNavigate 钩子来进行路由跳转,无需像 v5 中那样使用 history 对象或 withRouter 高阶组件。
useNavigate 钩子返回一个 navigate 函数,该函数可以接收一个字符串参数,表示要跳转的路由路径。在组件内部调用 navigate 函数,就可以进行路由跳转操作。
下面是一个使用 useNavigate 进行路由跳转的示例:
import React from 'react';
import { useNavigate } from 'react-router-dom';
function MyComponent() {
const navigate = useNavigate();
const handleClick = () => {
navigate('/some/path');
};
return <button onClick={handleClick}>跳转到 /some/path</button>;
}
export default MyComponent;
在上面的示例中,我们使用 useNavigate 钩子获取到 navigate 函数,并在点击事件处理函数 handleClick 中调用该函数进行路由跳转。需要注意的是,由于 useNavigate 是一个钩子,因此只能在函数组件中使用,不能在类组件中使用。
React Router v6 element一锅端
React Router 6 改变了路由组件的渲染方式,引入了 element 属性作为渲染路由组件的方法。但是,React Router 6 中仍然可以使用 component 和 render 属性来渲染路由组件。
在 React Router 5 中,component 属性和 render 属性可以用来指定渲染路由组件的方法,例如:
import { Route } from 'react-router-dom';
function Home() {
return <h1>Home Page</h1>;
}
<Route path="/" component={Home} />
<Route path="/about" render={(props) => <h1>About Page</h1>} />
而在 React Router 6 中,element 属性可以用来指定渲染路由组件的方法,例如:
import { Route } from 'react-router-dom';
function Home() {
return <h1>Home Page</h1>;
}
<Route path="/" element={<Home />} />
<Route path="/about" element={<h1>About Page</h1>} />
可以看到,在 React Router 6 中使用 element 属性可以实现与 React Router 5 中使用 component 和 render 属性相同的效果。
简述react-router6的使用
- 安装 React Router v6
首先,我们需要使用 npm 或 yarn 安装 React Router v6:
npm install react-router-dom
- 创建路由器
在应用程序的入口处创建一个路由器,可以使用 <HashRouter> 组件,并传入一个路由配置对象。例如:
import { HashRouter } from 'react-router-dom';
import routes from './routes';
function App() {
return (
<HashRouter>
<Routes routes={routes}>
{/* 应用程序的其他组件 */}
</Routes>
</HashRouter>
);
}
export default App;
- 根组件外定义路由类型
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<Suspense fallback="loading">
{/* 在渲染 懒加载的 组件时,我们需要使用 <Suspense> 组件来包装它,这个组件会在组件加载时显示一个加载中的占位符。
在 fallback 属性中定义了一个加载中的占位符"loading"。这个占位符将在 MyComponent 组件加载完成之前显示。*/}
<HashRouter>
<App />
</HashRouter>
</Suspense>
);
- 根组件使用useRoutes传入routes配置
在路由配置中定义每个路由对应的组件,可以使用常规的 React 组件,例如:
// router/index.js
// 实现页面懒加载, 使用了 React.lazy() 方法来动态导入,这个方法接受一个返回 import() 方法的函数作为参数。
// 这样做的好处是,当应用程序加载时,它不会加载 MyComponent 组件,只有当我们尝试使用它时才会加载
const Home = React.lazy(()=>import('@/views/home'))
const Entire = React.lazy(()=>import('@/views/entire'))
const Detail = React.lazy(()=>import('@/views/detail'))
const routes = [
{
// 实现首次进入即进入home
path:"/",
element: <Navigate to="/home" />
},
{
path:"/home",
element: <Home/>
},
{
path:"/entire",
element: <Entire/>
},
{
path:"/detail",
element: <Detail/>
},
]
export default routes;
// App.js
import routes from "./router";
const App = memo(() => {
return (
<div className="app">
{/* 在此配置路由,使用router中的配置文件 */}
{useRoutes(routes)}
</div>
);
});
- 使用链接和导航
在应用程序中使用链接和导航到不同的路由,可以使用 <Link> 和 <NavLink> 组件进行链接,使用 useNavigate 钩子进行导航,例如:
import { Link, NavLink, useNavigate } from 'react-router-dom';
function Navigation() {
const navigate = useNavigate();
function handleClick() {
navigate('/entire');
}
return (
<nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<NavLink to="/detail" activeClassName="active">
About
</NavLink>
</li>
<li>
<button onClick={handleClick}>Go to Entire</button>
</li>
</ul>
</nav>
);
}
以上是使用 React Router 6 和 react-router-dom 的简要步骤,其中包含了路由器的创建、路由配置的定义、路由对应的组件的定义,以及如何使用链接和导航。需要注意的是,在 React Router 6 中,不再需要使用 withRouter 和 Route 组件,而是使用 Routes 和 useRoutes 钩子进行路由配置和匹配。