使用 next/router 添加具有相同键的多个查询参数

Jes*_*ton 5 query-string reactjs next.js next-router

我正在使用 Next.js 应用程序中的查询参数过滤来自 API 的结果。我想使用useRouter()相同的键推送多个不同的过滤器,因此我的查询参数可能如下所示:

?page=1&skill=html&skill=css&skill=js
Run Code Online (Sandbox Code Playgroud)

我可以将每个参数传递给我的 API 请求。现在,当我尝试添加技能参数时,我正在使用router.push它,如下所示:

const router = useRouter();

const addFilter = (skill: string) => router.push({ query: { ...router.query, skill: skill.toLowerCase() } });
Run Code Online (Sandbox Code Playgroud)

但显然它会覆盖之前的技能,所以我只能在 URL 中获得其中一个技能。如何使用相同的键添加其他查询参数,最好使用useRouter()or next/router

Jor*_*rge 5

为了操作 Next.js 中 URL 中的查询参数,我使用了一个自定义钩子,该钩子使用了 useRouter 提供的功能,但我还添加了一些 util 方法,在本例中,为了向 URL 添加过滤器,我使用了方法addParam

这是自定义钩子的主体。

const useRouterFilter = () =>{
  const { pathname, query, push } = useRouter()

  return {
    addParam,
    ...
  }
}
Run Code Online (Sandbox Code Playgroud)

这将是钩子内的 addFilter 方法:

  /**
   * Adds a query param to the URL string. Multiple params with the same name
   * and different values can be added.
   * @param name The name of the param.
   * @param value The value of the param.
   */
  const addParam = (name: string, value: string | boolean | number) => {
    const { [name]: param, ...rest } = query
    let newQuery

    if (!param) {
      newQuery = { ...rest, [name]: encodeURIComponent(value) }
    } else if (Array.isArray(param)) {
      if (param.indexOf(encodeURIComponent(value)) > -1) return
      newQuery = { ...rest, [name]: [...param, encodeURIComponent(value)] }
    } else {
      if (param === encodeURIComponent(value)) return
      newQuery = { ...rest, [name]: [param, encodeURIComponent(value)] }
    }

    push(
      {
        pathname,
        query: newQuery,
      },
      undefined,
      { shallow: true }
    )
  }
Run Code Online (Sandbox Code Playgroud)

在本例中,我使用push将参数添加到 URL,但replace也可以使用。

完整的钩子可以从以下要点复制