Next.js useRouter/withRouter在第一次渲染中查询时接收未定义

Next.js useRouter/withRouter在第一次渲染中查询时接收未定义,next.js,Next.js,我的动态路线有问题。看起来像这样 [lang]/abc 我试图从[lang]中获取查询值,但当我使用useRouter/withRouter时,我在页面的2-3次呈现期间得到了查询(第一次得到query.lang=undefined)。它可以在1渲染或使用任何技术 无法在第一次渲染时获取查询值 静态优化的页面没有提供路由参数。例如,query是一个空对象({}) 水合后,Next.js将填充查询对象 Next.js 10.0.5及更高版本 使用router.isReadyinsideuseffe

我的动态路线有问题。看起来像这样

[lang]/abc

我试图从
[lang]
中获取查询值,但当我使用
useRouter/withRouter
时,我在页面的2-3次呈现期间得到了查询(第一次得到
query.lang=undefined
)。它可以在1渲染或使用任何技术


无法在第一次渲染时获取查询值

静态优化的页面没有提供路由参数。例如,
query
是一个空对象(
{}

水合后,Next.js将填充查询对象

Next.js 10.0.5及更高版本 使用
router.isReady
inside
useffect
hook检查参数是否准备就绪。有关示例,请参见@dy063给出的答案

在Next.js 10.0.5之前 第一次渲染动态路由时,
router.asPath
router.route
是相等的。一旦
query
对象可用,
router.asPath
就会反映它

更改
asPath
后,您可以依赖
useffect
钩子中的查询值

const router = useRouter();

useEffect(() => {
  if (router.asPath !== router.route) {
    // router.query.lang is defined
  }
}, [router])

我解决了我的问题,我需要在Hoc组件中使用它。 我使用withRouter(withLocale(Comp))包装并在HOC中创建条件

export default function withLocale(WrappedPage) {
    const WithLocale = ({ router, ...props }) => {
        const { lang } = router.query;
        if (!lang || !isLocale(lang)) {
            return <Error statusCode={404} />;
        }
        return (
            <LocaleProvider lang={lang}>
                <WrappedPage {...props} />
            </LocaleProvider>
        );
    };
   return WithLocale;
}
使用Locale导出默认函数(WrappedPage){
const with locale=({router,…props})=>{
const{lang}=router.query;
如果(!lang | |!isLocale(lang)){
返回;
}
返回(
);
};
用locale返回;
}

在NextJS 9中,确保页面组件可以立即使用路由参数的一种方法是从传递到
getServerSideProps()
上下文中获取路由参数,并作为道具传递到组件

对于像
[id].js这样的页面

导出函数getServerSideProps(上下文){
返回{
道具:{params:context.params}
};
}
导出默认值({params})=>{
const{id}=params;
返回您用{id}打开的页面;
};

这是一部好作品,我从

添加
useQuery.ts
helper文件

//useQuery.js
从“下一个/路由器”导入{useRouter};
//解析查询或返回null
导出默认函数useQuery(){
const router=useRouter();
常量HaskeryParams=
/\[.+\]/.test(router.route)|/\?./.test(router.asPath);
const ready=!hasQueryParams | | Object.keys(router.query).length>0;
如果(!ready)返回null;
返回router.query;
}
用法

//在组件中(而不是useRouter)
const query=useQuery();
useffect(()=>{
如果(!查询){
返回;
}
log('my query exists!!',query);
},[查询];
我发现了一些东西:

isReady:布尔值-路由器字段是否已在客户端更新并准备好使用。应仅在useEffect方法内部使用,而不是在服务器上有条件地呈现。

代码如下:

const router=useRouter();
useffect(()=>{
如果(!router.isReady)返回;
//使用router.query的代码
},[router.isReady]);

在下一个9.4.4上尝试了这个,我得到了一个错误,因为
context.props
未定义的
,无法序列化为JSON。希望它会包含查询。是的,这不起作用。
context.props
context没有
props
,请看下面的示例。您的页面道具将从
getServerSideProps
接收您返回的
{props:{}}
。您好@Mycolaos,答案实际上是利用
上下文。参数
-而不是
上下文。道具
。只是在接下来的10分钟里重新确认了方法。参考:使用
getServerSideProps
指示Next.js在每个请求的服务器端预呈现页面。意味着它不是静态优化和缓存的。只有当你想牺牲表现时才使用它。例如,如果您必须在第一次渲染之前获取数据。tnx很多:))您应该小心使用这种方法,因为它有缺陷,因为
asPath
route
可以相等,这并不反映路由器的实际准备情况。只有当你的URL总是有一个查询时,你才能相信这一点。这应该是公认的答案。这正是isReady推出的目的。与其他可能产生奇怪副作用的棘手解决方案相比,它就像一个魅力!谢谢