如何在 NextJS 中向 Router.push 添加查询参数?

How do I add a query param to Router.push in NextJS?

使用 NextJS,我尝试使用具有 toas 字段的对象路由到另一个页面:

export const routes = {
  'BrowseList' : {
    'to' : '/apps/Browse/list',
    'as' : '/browse/list'
  }
  // ....
}

然后像这样导入和使用:

import { routes } from './__routes';
import Router from 'next/router';

// .... 

const { to, as } = routes.BrowseList;

Router.push(to, as);

一切正常。我的困境是我在附加查询参数时试图做类似的事情。我正在尝试根据 docs:

遵循此示例
Router.push({
  pathname: '/about',
  query: { name: 'Zeit' },
})

我尝试过的方法(无效):

Router.push({
  pathname : to,
  as,
  query    : { user_id: this.props.data.member.user.id },
});

这给了我

的控制台警告
Unknown key passed via urlObject into url.format: as

我知道我也许可以只使用字符串插值并做这样的事情:

Router.push(to, `${as}?user_id=`${this.props.data.member.user.id}`)

但我想知道文档示例中是否缺少某些内容,该示例还将查询参数添加到我的 as 值中。

谢谢。

next.js 中的路由器似乎没有任何方便的 API 来导航到使用查询字符串。

我使用 toQuery 方法创建了一个名为 LinkCreator 的实用程序 class,如下所示。它使用 query-string 创建查询字符串:

import * as qs from 'query-string';
export class LinkCreator {
    static query(object) {
        return qs.stringify(object);
    }
    static toQuery(object, path = "/") {
        const query = this.query(object);
        return path + '?' + query;
    }
}

然后,它可以像这样与 Router.push 一起使用:

Router.push(LinkCreator.toQuery({ name: 'Zeit' }), '/about');

你很接近@nyphur。 as 值作为 push 的第二个参数,而不是对应于 to 的对象内部(检查 router.d.ts 查看 push 是如何定义的)。这就是您收到错误 Unknown key passed via urlObject into url.format: as 的原因。在您提出问题 10 个月后,也许这对寻找答案的人仍然有用。假设您有办法为 as 参数构建查询字符串,按照@Gezim 的回答或通过任何其他方法:

Router.push({ pathname: to, query: { user_id: this.props.data.member.user.id } }, as, options);

注意: 根据@Gezim 的回答,如果您在第一个参数中格式化字符串或 pathname 以包含您的查询参数,它会工作但编码值,如果有的话,例如 %2B 将被解码,因此您将得到 +。如果查询参数对象进入 query,则不会发生这种情况。如果您有任何依赖于此的逻辑,请考虑这一点。

编辑:起初我认为通过传播合并对象是一个简单的解决方法,但后来评论指出需要进行一些更改,所以我更新了我的答案以继续使用传播,但不幸的是它现在确实使 Routes 变得更加复杂和复杂,但它的消耗仍然很直接。

为了安心,我也会冻结 Routes 对象。

import Router from 'next/router';

export const Routes = Object.freeze({
  BrowseList(query) {
    return [
      {
        pathname: '/apps/Browse/list',
        query
      },
      '/browse/list'
    ]
  }
  // ....
})

Router.push(
  ...Routes.BrowseList({
    paramName: "Param value here"
  })
)

额外的抽象

import Router from 'next/router';

const QueryRoutePath = (to, as, query) => ([
  {
    pathname: to,
    query
  },
  as
])

export const Routes = Object.freeze({
  BrowseList(query) {
    return QueryRoutePath(
      '/apps/Browse/list',
      '/browse/list',
      query)
  }
  // ....
})

const query = {
  paramName: "Param value here"
}

Router.push(
  ...Routes.BrowseList(query)
)