Next.js如何阻止router.replace修改自定义html lang属性?
问题:阻止Next.js在路由操作时修改HTML的lang属性
我在Next.js中使用i18n路由,next.config.js配置如下:
module.exports = { i18n: { locales: ['en', 'fr', 'nl'], defaultLocale: 'en', }, }
通过_document.js将HTML的lang属性覆盖为en-IN:
export default function Document() { return ( <Html lang="en-IN"> <Head /> <body> <Main /> <NextScript /> </body> </Html> ) }
但调用router.replace()添加查询参数时,HTML的lang属性会被自动修改为当前路由对应的locale(即en),相关代码如下:
export default function IndexPage(props) { const router = useRouter(); const addQueryParam = () => { router.replace( { query: { foo: 'bar' } }, { query: { foo: 'bar' } }, { shallow: true } ); }; return ( <div> <h1>Index page </h1> <button onClick={addQueryParam}>Add Query Param</button> </div> ); }
根据Next.js的i18n路由文档说明,这是为SEO设计的默认行为,但我需要阻止这个自动修改。
解决方案
方法1:在_app.js中监听路由变化,强制重置lang属性
在自定义的_app.js中,通过useEffect监听路由的locale变化,每次变化后手动将HTML的lang属性设置为目标值:
import { useEffect } from 'react'; import { useRouter } from 'next/router'; export default function MyApp({ Component, pageProps }) { const router = useRouter(); useEffect(() => { // 每次路由更新后,强制覆盖lang属性 document.documentElement.lang = 'en-IN'; }, [router.locale]); return <Component {...pageProps} />; }
方法2:在_document.js中通过生命周期钩子强制设置lang
利用_document.js的客户端生命周期钩子,在组件挂载后强制锁定lang属性:
import Document, { Html, Head, Main, NextScript } from 'next/document'; export default class MyDocument extends Document { static async getInitialProps(ctx) { const initialProps = await Document.getInitialProps(ctx); return { ...initialProps }; } componentDidMount() { // 客户端渲染完成后,强制设置lang属性 document.documentElement.lang = 'en-IN'; } render() { return ( <Html lang="en-IN"> <Head /> <body> <Main /> <NextScript /> </body> </Html> ); } }
核心原理
Next.js在路由切换时会自动根据当前路由的locale更新HTML的lang属性,因此我们需要在路由变化的生命周期节点中,强制将lang属性重置为自定义值,覆盖框架的默认行为。
内容的提问来源于stack exchange,提问作者Ankit Chaudhary
相关产品推荐
相关产品推荐

