先创建个 Next.js 项目
pnpm create next-app --typescript
"dependencies": {
"next": "13.0.0",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-router-dom": "^6.4.2"
},
"devDependencies": {
"@types/node": "18.11.6",
"@types/react": "18.0.23",
"@types/react-dom": "18.0.7",
"eslint": "8.26.0",
"eslint-config-next": "13.0.0",
"typescript": "4.8.4"
}
创建路由组件 components\MyRouter.tsx
使用 Hash 路由
import { lazy } from "react";
import { RouterProvider, createHashRouter as createRouter } from "react-router-dom";
let Login = lazy(() => import("./Login"));
let Layout = lazy(() => import("./Layout"));
let Home = lazy(() => import("./Home"));
let Log = lazy(() => import("./Log"));
// 只是例子,随便写写
let router = createRouter([
{
path: "/login",
element: <Login />,
loader: () => {
return "我是 loder data";
},
},
{
element: <Layout />,
children: [
{
path: "/",
element: <Home />,
},
{
path: "/log",
element: <Log />,
},
{
path: "*",
element: (
<>
<h1>error 404</h1>
</>
),
},
],
},
]);
export default function MyRouter() {
return (
<>
<RouterProvider router={router}></RouterProvider>
</>
);
}
创建组件 components\Layout\index.tsx
关键代码是 Suspense
与 Outlet
路由跳转 JSX 中使用 Link
Hook 中使用 useNavigate
react-router 相关请看官网,这里不再赘述.
import { FC, memo, Suspense } from "react";
import { Link, Outlet } from "react-router-dom";
interface IProps {}
let Index: FC<IProps> = function (props) {
return (
<>
<h1>Layout\index.tsx</h1>
<ul>
<li>
<Link to="/login">login</Link>
</li>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/log">log</Link>
</li>
</ul>
<Suspense fallback="loading">
<Outlet />
</Suspense>
</>
);
};
export default memo(Index);
在 pages/index.tsx
中使用 dynamic
导入 MyRouter
, 并设置 ssr: false
使用 Suspense
包裹 MyRouter
import dynamic from "next/dynamic";
import { FC, memo, Suspense } from "react";
const MyRouter = dynamic(() => import("../components/MyRouter"), { ssr: false });
interface IProps {}
let Index: FC<IProps> = function (props) {
return (
<Suspense fallback="loading">
<MyRouter />
</Suspense>
);
};
export default memo(Index);
创建页面 pages/404.tsx
访问除首页(/
)外的地址时, Next.js 会进入到这个404页面,
这里使用 Next.js useRouter
将路由导航到首页 /
(因为 404 页面是属于 Next.js 的路由页面,
不在 react-dom 的 RouterProvider 中)
import { useRouter } from "next/router";
import { FC, memo, useEffect } from "react";
interface IProps {}
let Index: FC<IProps> = function () {
let router = useRouter();
useEffect(() => {
router.push("/");
}, [router]);
return <></>;
};
export default memo(Index);
Next.js 会将 pages 目录自动生成路由,
所以开发SPA , 自己的代码需要全部写到 components 或其他目录中.
|next-js-spa-demo
|components
| |Home
| | |index.tsx
| |Layout
| | |index.tsx
| |Log
| | |-index.tsx
| |Login
| | |index.tsx
| |MyRouter.tsx
|pages
| |404.tsx
| |index.tsx
| |_app.tsx
|pnpm-lock.yaml
|next.config.js
|package.json
|tsconfig.json
https://github.com/xxxxue/next-js-spa-demo