此次版本升级涉及改动较多,且不向下兼容
1. Switch组件换为Routes, Route组件的render换为element
// old
import {
Route, Switch, withRouter,
} from 'react-router-dom';
<Switch>
{routes.map(
({path, exact, component: Component, routes: Routes}) => (
<Route
key={path}
path={path}
exact={exact}
render={props => <Component {...props} routes={Routes} />}
/>),
)}
<Route render={props => <NoMatch {...props} />} />
</Switch>
// new
import {
Route, Routes, Navigate,
} from 'react-router-dom';
<Routes>
{routes.map(
({path, component: Component, children}) => (
<Route
key={path}
path={path}
element={<Component {...props} />}
>
// 子路由的写法,之前可以写在组件中的嵌套Switch中
{children && children.map(({ path, component: Component }) => {
if (path === '/wealth/set') {
return (<Route
element={<Navigate to="/wealth/set/mechanismset" />}
path="/wealth/set"
/>)}
return (
<Route
key={path}
path={path}
element={<Component {...props} />}
/>)
})}
</Route> )
)}
<Route render={(props) => <NoMatch {...props} />} />
</Routes>
2. Redirect组件废弃
// old
if(route.path == '/wealth/set'){
return <Redirect to={tabs[0].key} />
}
// new
<Route
element={<Navigate to={tabs[0].key} />}
path="/wealth/set"
/>
3.子路由的渲染及Outlet的使用
// old直接子组件中放Switch
//App.js
<Switch>
{routes.map(
({path, exact, component: Component, routes: Routes}) => (
<Route
key={path}
path={path}
exact={exact}
render={props => <Component {...props} routes={Routes} />}
/>),
)}
<Route render={props => <NoMatch {...props} />} />
</Switch>
// child.js
<Switch>
{
// App.js 拿到传过来的值,并循环配置路由
this.props.routes.map((route, key) => {
if (route.path == '/wealth/set') {
return <Redirect to={tabs[0].key} key={key} />
}
return <Route key={key} exact={route.exact} path={route.path} render={(props) => <route.component {...props} />} />
})
}
</Switch>
// new app中嵌套路由,由Outlet做展示
// App.js
<Routes>
{routes.map(
({path, component: Component, children}) => (
<Route
key={path}
path={path}
element={<Component {...props} />}
>
// 子路由的写法,之前可以写在组件中的嵌套Switch中
{children && children.map(({ path, component: Component }) => {
if (path === '/wealth/set') {
return (<Route
element={<Navigate to="/wealth/set/mechanismset" />}
path="/wealth/set"
/>)}
return (
<Route
key={path}
path={path}
element={<Component {...props} />}
/>)
})}
</Route> )
)}
<Route render={(props) => <NoMatch {...props} />} />
</Routes>
// child.js
<Outlet {...this.props} />
4. withRouter废弃
// 实现withRouter
import React from 'react';
import { useLocation, useNavigate, useParams } from 'react-router-dom';
export default function withRouter(Child) {
return function(props) {
const location = useLocation();
const navigate = useNavigate();
const params = useParams();
return <Child {...props} navigate={navigate} params={params} location={location} />;
}
}
5. Prompt废弃
重写BrowserRouter,替换'react-router-dom'的BrowserRouter
// 需要先给BrowserRouter注入history对象
import React from 'react';
import { createBrowserHistory } from "history";
import { Router } from "react-router";
const browserHistory = createBrowserHistory({ window });
const BrowserRouter = ({
basename,
children,
window,
}) => {
let historyRef = React.useRef();
if (historyRef.current == null) {
historyRef.current = browserHistory;
}
let history = historyRef.current;
let [state, setState] = React.useState({
action: history.action,
location: history.location,
});
React.useLayoutEffect(() => history.listen(setState), [history]);
return (
<Router
basename={basename}
children={children}
location={state.location}
navigationType={state.action}
navigator={history}
/>
);
}
export {
browserHistory as history,
BrowserRouter
}
实现Prompt
import React, { useEffect } from 'react';
import {history} from '../BrowserRouter';
import {useLocation, useNavigate} from 'react-router-dom';
const Prompt = (props) => {
const location = useLocation();
const navigate = useNavigate();
// 存储关闭阻止页面切换的方法(调用此方法将关闭阻止页面切换)
let unblock = null;
// 阻止页面卸载
const beforeUnload = (event) => {
event.preventDefault();
event.returnValue = '';
}
// 页面切换时的回调
const handlePageChange = async ({location,action}) => {
// 是否关闭切换限制并跳转
let toNext = false;
if (props.message) {
if (typeof props.message === "string") {
toNext = confirm(props.message);
} else {
toNext = await props.message(location,action);
}
} else {
toNext = confirm("是否放弃更改");
}
toNext && closeBlockAndNavigate(nextLocation);
}
// 关闭阻止页面切换
const closeBlockPageSwitching = () => {
if (unblock) {
unblock();
unblock = null;
window.removeEventListener("beforeunload", beforeUnload);
}
}
// 关闭阻止页面切换,并跳转
const closeBlockAndNavigate = (nextLocation) => {
closeBlockPageSwitching();
navigate(nextLocation);
}
// 监听when 和 pathname 变化,当发生变化时判断是否需要开启block navigate.
useEffect(() => {
if (props.when) {
// 阻塞页面跳转(history行为)
unblock = history.block(handlePageChange);
window.addEventListener('beforeunload', beforeUnload);
}
return () => {
props.when && closeBlockPageSwitching();
}
}, [props.when, location.pathname]);
return (
<></>
);
}
export default Prompt;
6. history对象废弃,路由跳转使用navigate代替
// old
history.go(n)
history.goBack()
history.goForward()
history.push(location);
history.replace(location);
// new
navigate(-1); // history.goBack();
navigate(1); // history.goForward();
navigate(location); // history.push(location);
navigate(location, { replace: true }); // history.replace(location);
7. 路由传参方式修改及参数获取方式
// old
history.push({
pathname: '/home',
search: qs.stringify({ the: 'query' }),
state: { some: 'state' },
query: 'state'
});
history.push( '/home',{ some: 'state' })
//取值
const {pathname, hash, state, search, query} = history.location;
// new
navigate( '/home', {state: {some: 'state' },replace: true,})
navigate({ pathname: '/home', search: qs.stringify({ the: 'query' }) })}
const { state, pathname, search} = this.props.location;
8. 删除match对象
// old
const {params, url, path, isExact} = this.props.match;
// new
const { params } = this.props;
const { state, pathname, search} = this.props.location;
网友评论