上集回顾

在 data router 中如何优雅的跳转路由?

因为 router 对象返回了 navigate 方法,所以可以直接调用

// history.js
export const routes: ReturnType<typeof createBrowserRouter> = createBrowserRouter([
  {
    path: '/',
    element: <Home />,
  },
  {
    path: '/login',
    element: <div>login</div>,
  },
]);

// Home.js
import { routes } from '../history.tsx';

const Home = () => {
  return (
    <div>
      <button
        onClick={() => {
          routes.navigate('login');
        }}
      >
        go login
      </button>
    </div>
  );
};

// app.js
function App() {
  return <RouterProvider router={routes} />;
}

在非 data router

来看下 umi 是怎么实现的。

pnpm add history
histort.js
import { createBrowserHistory } from 'history'; // 注意语法 const history = createBrowserHistory(); export default history;
app.js
import BrowserRouter from 'components/BrowserRouter'; import history from 'xxx/history'; import Home from 'components/home'; function Routes() { return useRoutes([ { path: '/', element: <Home />, }, { path: 'login', element: <div>login</div>, }, ]); } const App = () => { return ( <BrowserRouter history={history}> <Routes /> </BrowserRouter> ); };
BrowserRouter.js
import React from 'react'; import type { History } from 'history'; import type { BrowserRouterProps as NativeBrowserRouterProps } from 'react-router-dom'; import { Router } from 'react-router-dom'; export interface BrowserRouterProps extends Omit<NativeBrowserRouterProps, 'window'> { history: History; } const BrowserRouter: React.FC<BrowserRouterProps> = React.memo((props) => { const { history, ...restProps } = props; const [state, setState] = React.useState({ action: history.action, location: history.location, }); React.useLayoutEffect(() => history.listen(setState), [history]); return ( <Router {...restProps} location={state.location} navigationType={state.action} navigator={history} /> ); }); export default BrowserRouter;