Next.js 路由器在第一次渲染时返回未定义的查询参数?
Next.js router is returning query parameters as undefined on first render?
我的 Next.js 应用程序中有一个页面执行以下操作:
- 这是一个搜索页面
- 路径名如下:
/search?q=search+slug
- 它在客户端加载数据
- 需要读取
router.query
得到router.query.q
值
PS: 我正在使用 Redux
const dispatch = useDispatch();
const router = useRouter();
const query = router.query as { q: string };
const queryString = query.q;
console.log("SEARCH CONTAINER");
console.log(`queryString: ${queryString}`);
useEffect(() => {
dispatch(THUNK.LOAD(queryString));
return () => { dispatch(ACTION.RESET_STATE()); };
},[dispatch,queryString]);
见useEffect
。理论上应该 运行 每个 queryString
一次(实际上是 req.query.q
)。
但我得到了重复的 THUNK.LOAD
操作。这就是我在此处添加 console.log()
的原因。
这就是它注销的内容:
然后:
这就是我收到重复发送的原因。当然我可以在发货前检查if (queryString)
,或者我可以从window.location.search
中获取。但令我惊讶的是 router.query.q
首先出现的是 undefined
。这怎么可能呢?为什么要异步填充 req.query
对象?对此有何解释?
那是因为 nextjs 在服务器端和客户端都可以工作,因此有必要通过执行 typeof window !== 'undefined'
之类的操作来检查您实际上是在服务器上还是在客户端上,因为组件需要在客户端上被水合边.
当你使用 useRouter
挂钩时,由于显而易见的原因,它只在客户端运行,但是当 nextjs 将“组件”传递给浏览器时,它不知道 router.query.q
指的是什么,只有当组件在客户端水合时,反应挂钩才会启动,然后您可以检索 queryString
这也类似于您需要使用 dynamic
导入的原因
大多数客户端库的 nextjs 应用程序。
P.S。我自己是 nextjs 的新手,但我希望这是有道理的。
刚刚发现我的问题的解决方案:
发件人:https://nextjs.org/docs/api-reference/next/router#router-object
isReady
: boolean
- Whether the router fields are updated
client-side and ready for use. Should only be used inside of
useEffect
methods and not for conditionally rendering on the server.
这是当您点击 /search?q=XXX
时客户端 router.query
发生的情况。
第一次渲染
router.isReady: false
router.query: {}
后续渲染
router.isReady: true
router.query: {"q":"xxx"}
结论
第一个 运行 客户端(对于 SSG 页面)未填充 router.query
这一事实是一个设计实现细节。您可以通过检查 router.isReady
布尔值 属性.
来监控它是否已被填充
基于@cbdeveloper 的回答,这里是示例代码 运行 NextJS 用于在客户端渲染期间获取路由器数据:
文件名:/pages/[...results].tsx
import { useRouter } from 'next/router';
import { useEffect, useState } from 'react';
export default function Results() {
const router = useRouter();
const { q } = router.query;
const [searchQuery, setSearchQuery] = useState("");
useEffect(() => {
console.log(`useEffect triggered`);
router.isReady ? setSearchQuery(q as string) : console.log('router is not ready');
},[q]);
return (
<>
<p>q: {router.query.q}</p>
<p>searchQuery: {searchQuery}</p>
<p>bar: {router.query.bar}</p>
<form>
<label>Search Query:</label>
<input
type="text"
name="q"
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
/>
<button type="submit">Submit</button>
</form>
</>
);
}
This solution 为我工作:
const router = useRouter();
React.useEffect(() => {
if (router.isReady) {
// Code using query
console.log(router.query);
}
}, [router.isReady]);
我的 Next.js 应用程序中有一个页面执行以下操作:
- 这是一个搜索页面
- 路径名如下:
/search?q=search+slug
- 它在客户端加载数据
- 需要读取
router.query
得到router.query.q
值
PS: 我正在使用 Redux
const dispatch = useDispatch();
const router = useRouter();
const query = router.query as { q: string };
const queryString = query.q;
console.log("SEARCH CONTAINER");
console.log(`queryString: ${queryString}`);
useEffect(() => {
dispatch(THUNK.LOAD(queryString));
return () => { dispatch(ACTION.RESET_STATE()); };
},[dispatch,queryString]);
见useEffect
。理论上应该 运行 每个 queryString
一次(实际上是 req.query.q
)。
但我得到了重复的 THUNK.LOAD
操作。这就是我在此处添加 console.log()
的原因。
这就是它注销的内容:
然后:
这就是我收到重复发送的原因。当然我可以在发货前检查if (queryString)
,或者我可以从window.location.search
中获取。但令我惊讶的是 router.query.q
首先出现的是 undefined
。这怎么可能呢?为什么要异步填充 req.query
对象?对此有何解释?
那是因为 nextjs 在服务器端和客户端都可以工作,因此有必要通过执行 typeof window !== 'undefined'
之类的操作来检查您实际上是在服务器上还是在客户端上,因为组件需要在客户端上被水合边.
当你使用 useRouter
挂钩时,由于显而易见的原因,它只在客户端运行,但是当 nextjs 将“组件”传递给浏览器时,它不知道 router.query.q
指的是什么,只有当组件在客户端水合时,反应挂钩才会启动,然后您可以检索 queryString
这也类似于您需要使用 dynamic
导入的原因
大多数客户端库的 nextjs 应用程序。
P.S。我自己是 nextjs 的新手,但我希望这是有道理的。
刚刚发现我的问题的解决方案:
发件人:https://nextjs.org/docs/api-reference/next/router#router-object
isReady
:boolean
- Whether the router fields are updated client-side and ready for use. Should only be used inside ofuseEffect
methods and not for conditionally rendering on the server.
这是当您点击 /search?q=XXX
时客户端 router.query
发生的情况。
第一次渲染
router.isReady: false
router.query: {}
后续渲染
router.isReady: true
router.query: {"q":"xxx"}
结论
第一个 运行 客户端(对于 SSG 页面)未填充 router.query
这一事实是一个设计实现细节。您可以通过检查 router.isReady
布尔值 属性.
基于@cbdeveloper 的回答,这里是示例代码 运行 NextJS 用于在客户端渲染期间获取路由器数据:
文件名:/pages/[...results].tsx
import { useRouter } from 'next/router';
import { useEffect, useState } from 'react';
export default function Results() {
const router = useRouter();
const { q } = router.query;
const [searchQuery, setSearchQuery] = useState("");
useEffect(() => {
console.log(`useEffect triggered`);
router.isReady ? setSearchQuery(q as string) : console.log('router is not ready');
},[q]);
return (
<>
<p>q: {router.query.q}</p>
<p>searchQuery: {searchQuery}</p>
<p>bar: {router.query.bar}</p>
<form>
<label>Search Query:</label>
<input
type="text"
name="q"
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
/>
<button type="submit">Submit</button>
</form>
</>
);
}
This solution 为我工作:
const router = useRouter();
React.useEffect(() => {
if (router.isReady) {
// Code using query
console.log(router.query);
}
}, [router.isReady]);