【问题标题】:Protect routes with getInitialProps - Next.js使用 getInitialProps 保护路由 - Next.js
【发布时间】:2020-02-04 19:39:32
【问题描述】:

我们目前正在处理特定于用户的流程,即需要一些保护措施来防止用户访问某些页面。我们基于来自 GraphQL API 的数据来执行此操作,据我们所知,我们应该在 getInitialProps 中实现这些保护。

我们想为此使用一些实用函数,而不是重写每个页面上的所有逻辑。看这里的一个例子:

来自我们的 getInitialProps 的片段

Email.getInitialProps = async ({ req, res, apolloClient }) => {
  const deviceInfo = getDeviceInfo(req)

  try {
    const {
      data: { viewer },
    } = await apolloClient.query({
      query: GET_CHECKOUT,
      fetchPolicy: 'network-only',
    })

    checkForCart(viewer, res)
    checkForProcessingPayment(viewer, res)

    return {
      namespacesRequired: ['buy-common', 'common', 'buy-email'],
      deviceInfo,
    }
  } catch (error) {
    const { href, as } = getLinkProps('CART')
    return redirect({ href, as }, res)
  }
}

实用程序函数(handleRedirect 只是一个重定向实用程序,它在后台执行 res.redirectres.end

export const checkForCart = ({ cart, checkout }, res) => {
  const { rows = [] } = checkout || {}

  if (!cart || !rows.length) {
    return handleRedirect('CART', res)
  }
}

这看起来不错,因为我们可以使用checkForCart(),而不是对每个页面重复此代码。它有一个问题,那就是checkForCart util 的return 只返回函数,而不是返回页面。所以,因为重定向需要一些时间,所以checkForCart() get 下面的代码会被执行。因此,如果我在checkForCart(viewer, res) 下方执行console.log,它将记录下来。

有没有一种巧妙的方法来停止从 util 执行,或者 Next.js 中是否有一种巧妙的方法来修复这样的情况?实现“守卫”之类的最佳方式是什么?

【问题讨论】:

  • 在 HOC 组件中执行 checkForCart 和所有其他逻辑怎么样?
  • 嘿@NicolòCozzani 感谢您的建议,但是我们阻止使用 HOC,所以这对我们来说并不是一个真正的选择,但下面的答案帮助了我们:)

标签: javascript graphql next.js


【解决方案1】:

getInitialProps 是一个async 函数,这意味着您可以利用await 语法。将checkForCart 转换为返回promise 的函数和await 它,然后处理结果。例如:

export const checkForCart = ({ cart, checkout }, res) => {
  const { rows = [] } = checkout || {}
  return new Promise((resolve, reject) => {
    if (!cart || !rows.length) {
      reject()
    }
    resolve()
  })
}

Email.getInitialProps = async ({ req, res, apolloClient }) => {
  const deviceInfo = getDeviceInfo(req)

  try {
    const {
      data: { viewer },
    } = await apolloClient.query({
      query: GET_CHECKOUT,
      fetchPolicy: 'network-only',
    })

    // If this rejects/fails because !cart || !rows.length
    // execution will jump to the catch block
    await checkForCart(viewer, res)

    // This won't run until checkForCart finishes and resolves
    checkForProcessingPayment(viewer, res)

    return {
      namespacesRequired: ['buy-common', 'common', 'buy-email'],
      deviceInfo,
    }
  } catch (error) {
    const { href, as } = getLinkProps('CART')
    return redirect({ href, as }, res)
  }
}

【讨论】:

  • 感谢您的帮助!我们确实使用了 Promise,只是方式不同。例如,如果cart || rows.length 为真,我们不会拒绝,而是解决。否则我们只是重定向而不拒绝,因为没有解析/拒绝,等待实际上会等待,因此用户会被重定向。
猜你喜欢
  • 2021-03-29
  • 2021-08-06
  • 1970-01-01
  • 2019-10-12
  • 2020-12-19
  • 1970-01-01
  • 1970-01-01
  • 2021-05-14
  • 2022-10-30
相关资源
最近更新 更多