在 Next.js 中使用 react-router-dom
React 和 Next.js 是目前前端最热门的技术之一,而 react-router-dom 是 React 生态系统中最流行的路由库之一。在 Next.js 中使用 react-router-dom 可以帮助开发者实现前端路由的功能,同时提高开发效率。
本文将指导大家如何在 Next.js 中安装和配置 react-router-dom,并且给出详细的代码示例。
安装 react-router-dom
在使用 react-router-dom 之前,需要安装它。可以使用 npm 或者 yarn 进行安装。
使用 npm:
npm install react-router-dom
或者使用 yarn:
yarn add react-router-dom
安装完成后,就可以在项目中使用 react-router-dom 了。
配置 react-router-dom
在 Next.js 中使用 react-router-dom 需要先配置一些基础代码。首先,在 pages 目录下新建一个名为 _app.js 的文件,在文件中添加以下代码:
// www.javascriptcn.com code example
import { useEffect } from 'react'
import { useRouter } from 'next/router'
import * as gtag from '../lib/gtag' // gtag 是 Google Analytics 的代码库,可以根据需要修改
export default function App({ Component, pageProps }) {
const router = useRouter()
useEffect(() => {
const handleRouteChange = (url) => {
gtag.pageview(url) // 发送页面浏览事件到 GA
}
router.events.on('routeChangeComplete', handleRouteChange)
return () => {
router.events.off('routeChangeComplete', handleRouteChange)
}
}, [router.events])
return <Component {...pageProps} />
}这段代码的作用是在页面路由发生变化时,发送事件到 Google Analytics(GA),以便进行数据统计和分析。这段代码已经配置好了,但是需要根据项目实际情况修改 gtag。
然后,在 pages 目录下新建一个名为 _document.js 的文件,在文件中添加以下代码:
// www.javascriptcn.com code example
import Document, { Html, Head, Main, NextScript } from 'next/document'
import { ServerStyleSheet } from 'styled-components'
export default class MyDocument extends Document {
static async getInitialProps(ctx) {
const sheet = new ServerStyleSheet()
const originalRenderPage = ctx.renderPage
try {
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: (App) => (props) => sheet.collectStyles(<App {...props} />),
})
const initialProps = await Document.getInitialProps(ctx)
return {
...initialProps,
styles: (
<>
{initialProps.styles}
{sheet.getStyleElement()}
</>
),
}
} finally {
sheet.seal()
}
}
render() {
return (
<Html>
<Head>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" />
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
}这段代码主要是配置服务器端渲染时使用的样式表和字体等资源。这段代码也已经配好了,不需要进行修改。
路由配置
完成基础配置之后,就可以开始进行路由配置了。在 pages 目录下新建一个名为 index.js 的文件,并添加以下代码:
// www.javascriptcn.com code example
import { Link } from 'react-router-dom'
export default function Home() {
return (
<div>
<h1>这是首页</h1>
<Link to="/about">关于我们</Link>
</div>
)
}这段代码是一个简单的页面,其中包含了一个 Link 组件。Link 组件用于在页面中生成链接,当用户点击链接时,它会进行路由跳转。
同样,再在 pages 目录下新建一个名为 about.js 的文件,并添加以下代码:
// www.javascriptcn.com code example
import { Link } from 'react-router-dom'
export default function About() {
return (
<div>
<h1>这是关于我们页面</h1>
<Link to="/">返回首页</Link>
</div>
)
}这段代码也是一个简单的页面,它也包含了一个 Link 组件,并且链接指向首页。
在 pages 目录下新建一个名为 _error.js 的文件,并添加以下代码:
// www.javascriptcn.com code example
import { Link } from 'react-router-dom'
export default function Error() {
return (
<div>
<h1>页面不存在</h1>
<Link to="/">返回首页</Link>
</div>
)
}这段代码是一个错误页面,当用户访问一个不存在的页面时,会显示该页面。
在 pages 目录下新建一个名为 [...slug].js 的文件,并添加以下代码:
// www.javascriptcn.com code example
import { useRouter } from 'next/router'
export default function DynamicPage() {
const router = useRouter()
const { slug } = router.query
return (
<div>
<h1>
你正在访问动态页面: <code>{slug}</code>
</h1>
</div>
)
}这段代码是一个动态页面,它使用 Next.js 的路由配置语法 ([...slug].js) 来实现动态路由。当用户访问该页面时,路由参数将被传递到该页面组件中,可以在 router.query 中获取到。
最后,在 pages 目录下新建一个名为 404.js 的文件,并添加以下代码:
// www.javascriptcn.com code example
import { Link } from 'react-router-dom'
export default function NotFound() {
return (
<div>
<h1>页面不存在</h1>
<Link to="/">返回首页</Link>
</div>
)
}这段代码是一个默认的 404 页面,当用户访问了一个不存在的页面时,会显示该页面。
路由配置完成后,需要将配置的路由导出,以供 Next.js 使用。在 pages 目录下新建一个名为 _routes.js 的文件,并添加以下代码:
// www.javascriptcn.com code example
import Home from './index'
import About from './about'
import NotFound from './404'
import DynamicPage from './[...slug]'
const routes = [
{
path: '/',
component: Home,
exact: true,
},
{
path: '/about',
component: About,
exact: true,
},
{
path: '/dynamic/:slug*',
component: DynamicPage,
exact: true,
},
// 配置默认的 404 页面
{
component: NotFound,
},
]
export default routes这段代码定义了路由的配置,包括页面的路径、组件、是否需要精确匹配等信息。最后一个配置是默认的 404 页面,它会匹配所有无法匹配的路由。需要注意的是,/dynamic/:slug* 配置中的 * 是表示通配符,它可以匹配路径中任何内容。
现在,路由已经配置完成了,已经可以进行页面跳转和路由匹配了。
使用 react-router-dom
在 Next.js 中使用 react-router-dom 的关键是将 pages/_app.js 中包装 <Component> 组件的 <BrowserRouter> 替换为 <StaticRouter>。<BrowserRouter> 是用于支持客户端路由的组件,但是由于 Next.js 是服务器渲染应用程序,因此需要使用 <StaticRouter>。
在 pages/_app.js 文件中,可以使用以下代码替换 <BrowserRouter>:
// www.javascriptcn.com code example
// import { BrowserRouter } from 'react-router-dom'
import { StaticRouter } from 'react-router-dom'
export default function App({ Component, pageProps, router }) {
// 省略原有代码
return (
// <BrowserRouter>
<StaticRouter location={router.asPath}>
<Component {...pageProps} />
</StaticRouter>
// </BrowserRouter>
)
}
// 省略原有代码这样,react-router-dom 就可以在 Next.js 中正常使用了。
完整代码示例
以下是完整的代码示例,用于演示在 Next.js 中使用 react-router-dom。
pages/_app.js
// www.javascriptcn.com code example
import { useEffect } from 'react'
// import { BrowserRouter } from 'react-router-dom'
import { StaticRouter } from 'react-router-dom'
import { useRouter } from 'next/router'
import * as gtag from '../lib/gtag'
export default function App({ Component, pageProps, router }) {
const router = useRouter()
useEffect(() => {
const handleRouteChange = (url) => {
gtag.pageview(url)
}
router.events.on('routeChangeComplete', handleRouteChange)
return () => {
router.events.off('routeChangeComplete', handleRouteChange)
}
}, [router.events])
return (
// <BrowserRouter>
<StaticRouter location={router.asPath}>
<Component {...pageProps} />
</StaticRouter>
// </BrowserRouter>
)
}
// 省略原有代码pages/_document.js
// www.javascriptcn.com code example
import Document, { Html, Head, Main, NextScript } from 'next/document'
import { ServerStyleSheet } from 'styled-components'
export default class MyDocument extends Document {
static async getInitialProps(ctx) {
const sheet = new ServerStyleSheet()
const originalRenderPage = ctx.renderPage
try {
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: (App) => (props) => sheet.collectStyles(<App {...props} />),
})
const initialProps = await Document.getInitialProps(ctx)
return {
...initialProps,
styles: (
<>
{initialProps.styles}
{sheet.getStyleElement()}
</>
),
}
} finally {
sheet.seal()
}
}
render() {
return (
<Html>
<Head>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" />
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
}pages/index.js
// www.javascriptcn.com code example
import { Link } from 'react-router-dom'
export default function Home() {
return (
<div>
<h1>这是首页</h1>
<Link to="/about">关于我们</Link>
<br />
<Link to="/dynamic/123">动态页面 (123)</Link>
</div>
)
}pages/about.js
// www.javascriptcn.com code example
import { Link } from 'react-router-dom'
export default function About() {
return (
<div>
<h1>这是关于我们页面</h1>
<Link to="/">返回首页</Link>
<br />
<Link to="/dynamic/456">动态页面 (456)</Link>
</div>
)
}pages/[...slug].js
// www.javascriptcn.com code example
import { useRouter } from 'next/router'
export default function DynamicPage() {
const router = useRouter()
const { slug } = router.query
return (
<div>
<h1>
你正在访问动态页面: <code>{slug}</code>
</h1>
</div>
)
}pages/404.js
// www.javascriptcn.com code example
import { Link } from 'react-router-dom'
export default function NotFound() {
return (
<div>
<h1>页面不存在</h1>
<Link to="/">返回首页</Link>
</div>
)
}pages/_routes.js
// www.javascriptcn.com code example
import Home from './index'
import About from './about'
import NotFound from './404'
import DynamicPage from './[...slug]'
const routes = [
{
path: '/',
component: Home,
exact: true,
},
{
path: '/about',
component: About,
exact: true,
},
{
path: '/dynamic/:slug*',
component: DynamicPage,
exact: true,
},
// 配置默认的 404 页面
{
component: NotFound,
},
]
export default routespages/_app.js
// www.javascriptcn.com code example
import { useEffect } from 'react'
// import { BrowserRouter } from 'react-router-dom'
import { StaticRouter } from 'react-router-dom'
import { useRouter } from 'next/router'
import * as gtag from '../lib/gtag'
export default function App({ Component, pageProps, router }) {
const router = useRouter()
useEffect(() => {
const handleRouteChange = (url) => {
gtag.pageview(url)
}
router.events.on('routeChangeComplete', handleRouteChange)
return () => {
router.events.off('routeChangeComplete', handleRouteChange)
}
}, [router.events])
return (
// <BrowserRouter>
<StaticRouter location={router.asPath}>
<Component {...pageProps} />
</StaticRouter>
// </BrowserRouter>
)
}
// 省略原有代码pages/_document.js
// www.javascriptcn.com code example
import Document, { Html, Head, Main, NextScript } from 'next/document'
import { ServerStyleSheet } from 'styled-components'
export default class MyDocument extends Document {
static async getInitialProps(ctx) {
const sheet = new ServerStyleSheet()
const originalRenderPage = ctx.renderPage
try {
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: (App) => (props) => sheet.collectStyles(<App {...props} />),
})
const initialProps = await Document.getInitialProps(ctx)
return {
...initialProps,
styles: (
<>
{initialProps.styles}
{sheet.getStyleElement()}
</>
),
}
} finally {
sheet.seal()
}
}
render() {
return (
<Html>
<Head>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" />
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
}pages/index.js
// www.javascriptcn.com code example
import { Link } from 'react-router-dom'
export default function Home() {
return (
<div>
<h1>这是首页</h1>
<Link to="/about">关于我们</Link>
<br />
<Link to="/dynamic/123">动态页面 (123)</Link>
</div>
)
}pages/about.js
// www.javascriptcn.com code example
import { Link } from 'react-router-dom'
export default function About() {
return (
<div>
<h1>这是关于我们页面</h1>
<Link to="/">返回首页</Link>
<br />
<Link to="/dynamic/456">动态页面 (456)</Link>
</div>
)
}pages/[...slug].js
// www.javascriptcn.com code example
import { useRouter } from 'next/router'
export default function DynamicPage() {
const router = useRouter()
const { slug } = router.query
return (
<div>
<h1>
你正在访问动态页面: <code>{slug}</code>
</h1>
</div>
)
}pages/404.js
// www.javascriptcn.com code example
import { Link } from 'react-router-dom'
export default function NotFound() {
return (
<div>
<h1>页面不存在</h1>
<Link to="/">返回首页</Link>
</div>
)
}pages/_routes.js
// www.javascriptcn.com code example
import Home from './index'
import About from './about'
import NotFound from './404'
import DynamicPage from './[...slug]'
const routes = [
{
path: '/',
component: Home,
exact: true,
},
{
path: '/about',
component: About,
exact: true,
},
{
path: '/dynamic/:slug*',
component: DynamicPage,
exact: true,
},
// 配置默认的 404 页面
{
component: NotFound,
},
]
export default routes以上就是在 Next.js 中使用 react-router-dom 的详细指南,希望对大家有所帮助。如果您有任何疑问或建议,欢迎在评论区留言。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67ca5112e46428fe9e251926