如何将NextJS的router.query.id转换为字符串?

huangapple go评论76阅读模式
英文:

How to type NextJS router.query.id as string?

问题

以下是您要的翻译内容:

UPDATE:

我现在更改为以下方式,似乎可以工作,但感觉不太对,不确定这是否是正确的做法。(使用这种方法,我只需要一次编写companyId as string,这是可以的。)

const CompanyPage: NextPage = () => {
  const router = useRouter()

  const companyId = router.query.id
  const { data: company } = api.companies.getSingleById.useQuery({companyId: companyId as string});

  if (!companyId || Array.isArray(companyId)) return <div>Loading...</div>; // 必须检查Array.isArray因为NextJS/Typescript存在问题
  if (!company ) return <div>Loading...</div>;

  ...
  return (...)
}

答案:

感谢Fabio的采纳答案。

我在其他路由中也将router.query解构成多个变量,以下是根据采纳的答案示例的方式:

const { companyId, locationId } = useMemo(() => ({
  companyId: router.query?.companyId?.toString() ?? "",
  locationId: router.query?.locationId?.toString() ?? "",
}), [router.query?.companyId, router.query?.locationId]);
英文:

I'm pretty new to TypeScript, as well as using the T3 stack (React Query / Tanstack Query). I'm trying to type companyId as string, so that I don't have to type companyId as string every time I use it later on it in the code, but I can't figure out how to best to that or what the best practice is with this stack... I'm used to plain old JavaScript and useEffects to do API calls (and probably writing worse code).

Note: the following code exists at /pages/companies/[id].tsx

The following is my first attempt, but I get a "Rendered more hooks than during the previous render" error at "const { data: company} ...", which makes sense:

const CompanyPage: NextPage = () =&gt; {
  const router = useRouter()

  const companyId = router.query.id
  if (!companyId || Array.isArray(companyId)) return &lt;div&gt;Loading...&lt;/div&gt; // have to check for Array.isArray because of NextJS/Typescript bug

  const { data: company } = api.companies.getSingleById.useQuery({companyId: companyId});
  if (!company ) return &lt;div&gt;Loading...&lt;/div&gt;

  ...
  return (...)

I tried doing the following, but I was not allowed because the type for companyId from router.query.id is string | string[] | undefined.

const CompanyPage: NextPage = () =&gt; {
  const router = useRouter()

  const companyId: string = router.query.id // Type &#39;string | string[] | undefined&#39; is not assignable to type &#39;string&#39;

  const { data: company } = api.companies.getSingleById.useQuery({companyId: companyId});
  if (!company ) return &lt;div&gt;Loading...&lt;/div&gt;

  ...
  return (...)

UPDATE:

I changed it to the following now, which seems to work, but it doesn't feel quite right it's the correct way to do things. (With this method, I only have to write companyId as string once, which is fine.)

const CompanyPage: NextPage = () =&gt; {
  const router = useRouter()

  const companyId = router.query.id
  const { data: company } = api.companies.getSingleById.useQuery({companyId: companyId as string});

  if (!companyId || Array.isArray(companyId)) return &lt;div&gt;Loading...&lt;/div&gt; // have to check for Array.isArray because of NextJS/Typescript bug
  if (!company ) return &lt;div&gt;Loading...&lt;/div&gt;

  ...
  return (...)

ANSWER:

Thank you to Fabio for the accepted answer.

I'm destructuring router.query into multiple variables on other routes, so this is an example of doing that based on the accepted answer:

const { companyId, locationId } = useMemo(() =&gt; ({
  companyId: router.query?.companyId?.toString() ?? &quot;&quot;,
  locationId: router.query?.locationId?.toString() ?? &quot;&quot;,
}), [router.query?.companyId, router.query?.locationId]);

答案1

得分: 2

你可以在与查询参数的 toString() 方法结合使用 optional chainingnullish coalescing,以下是基于你的代码片段的示例:

const CompanyPage: NextPage = () =&gt; {
  const router = useRouter();

  // 此结果将是字符串类型
  const companyId = useMemo(() =&gt; {
    return router.query?.id?.toString?.() ?? &quot;&quot;;
  }, [router.query?.id]);

  const { data: company } = api.companies.getSingleById.useQuery({
    companyId: companyId,
  });

  if (!company) return &lt;div&gt;Loading...&lt;/div&gt;;

  return; // ...
};

查询参数的类型为 string | string[] 的原因是,如果你有一个捕获所有段的路由,那么 URL 的每个部分将被以 / 分割并作为数组呈现给你。

示例

如果你的路由是 /some-segment/[...href],并且 URL 是 /some-segment/200/my-post,那么以下内容将适用:

  • href 查询变量的内容将是 [&quot;200&quot;, &quot;my-post&quot;]
  • 调用 href?.toString?.() 将返回 /some-segment/200/my-post
英文:

You can use optional chaining and nullish coalescing in combination with the query params' toString() method, heres an example based on your code snippet:

const CompanyPage: NextPage = () =&gt; {
  const router = useRouter();

  // this result will be of type string
  const companyId = useMemo(() =&gt; {
    return router.query?.id?.toString?.() ?? &quot;&quot;;
  }, [router.query?.id]);

  const { data: company } = api.companies.getSingleById.useQuery({
    companyId: companyId,
  });

  if (!company) return &lt;div&gt;Loading...&lt;/div&gt;;

  return; // ...
};

The reason why the query parameters are of type string | string[] is because if you had a catch-all segment each of the url parts will be split by / and presented to you as an array.

Example

If you had the route /some-segment/[...href] and the URL would be /some-segment/200/my-post following would apply:

  • The contents of the href query variable would be [&quot;200&quot;, &quot;my-post&quot;]
  • Calling href?.toString?.() would return you /some-segment/200/my-post.

huangapple
  • 本文由 发表于 2023年6月1日 22:01:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/76382726.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定