使用 getInitialProps 保护路线 - Next.js
Protect routes with getInitialProps - Next.js
我们目前正在处理用户特定的流程,这需要一些保护措施来防止用户访问某些页面。我们根据来自我们的 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.redirect
和 res.end
的重定向实用程序)
export const checkForCart = ({ cart, checkout }, res) => {
const { rows = [] } = checkout || {}
if (!cart || !rows.length) {
return handleRedirect('CART', res)
}
}
这看起来不错,因为我们可以使用 checkForCart()
而不是为每个页面重复此代码。它有一个问题,那就是 checkForCart
实用程序的 return
只返回函数,而不返回页面。因此,由于重定向需要一些时间,因此 checkForCart()
下面的代码得到执行。因此,如果我在 checkForCart(viewer, res)
下面执行 console.log
,它将记录。
是否有一种巧妙的方法来停止从 util 执行,或者在 Next.js 中是否有一种巧妙的方法来解决这种情况?实现类似 "guards" 的最佳方法是什么?
getInitialProps
是一个 async
函数,这意味着您可以利用 await
语法。将 checkForCart
转换为 returns 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)
}
}
我们目前正在处理用户特定的流程,这需要一些保护措施来防止用户访问某些页面。我们根据来自我们的 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.redirect
和 res.end
的重定向实用程序)
export const checkForCart = ({ cart, checkout }, res) => {
const { rows = [] } = checkout || {}
if (!cart || !rows.length) {
return handleRedirect('CART', res)
}
}
这看起来不错,因为我们可以使用 checkForCart()
而不是为每个页面重复此代码。它有一个问题,那就是 checkForCart
实用程序的 return
只返回函数,而不返回页面。因此,由于重定向需要一些时间,因此 checkForCart()
下面的代码得到执行。因此,如果我在 checkForCart(viewer, res)
下面执行 console.log
,它将记录。
是否有一种巧妙的方法来停止从 util 执行,或者在 Next.js 中是否有一种巧妙的方法来解决这种情况?实现类似 "guards" 的最佳方法是什么?
getInitialProps
是一个 async
函数,这意味着您可以利用 await
语法。将 checkForCart
转换为 returns 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)
}
}