首页 > 解决方案 > React Context 和 Apollo Client Link 之间的通信

问题描述

我正在使用 React 和 Apollo Client 开发单页 webapp,我想知道如何在 Apollo Client 链接和 React 上下文之间正确传达身份验证状态。

在客户端中,我编写了一个提供当前用户信息的 AuthProvider 上下文,因此我可以在组件树中的任何位置进行操作

const authState = useAuthState()
const dispatch = useAuthDispatch()

从而根据需要查询和更新身份验证信息。例如,我使用它来编写一个PrivateRoute组件,如果她没有经过身份验证,它会重定向查看器:

const PrivateRoute: FunctionComponent<RouteProps> = ({ children, ...rest }) => {
    const authState = useAuthState()

    return (
        <Route
            {...rest}
            render={({ location }) =>
                authState.user ? (
                    children
                ) : (
                    <Redirect
                        to={{
                            pathname: "/login",
                            state: { from: location }
                        }}
                    />
                )
            }
        />
    )
}

这一切都很好。当将此与我选择的身份验证形式(即 JWT)结合使用时,就会出现我的问题。我将访问令牌存储在 中,authState并且刷新令牌在登录时由后端设置为 httpOnly cookie。

但是我必须将访问令牌作为Authorization: Bearer每个请求的标头发送,我想使用 Apollo Link 执行此操作,如下所示:

const authLink = setContext(async (_, { headers }) => {
    const token = getTokenFromAuthStateSomehow()

    return {
        headers: {
            ...headers,
            authorization: token ? `Bearer ${token}` : ""
        }
    }
})

但这是在 Apollo Link 中,我当然无法直接访问 React 上下文。getTokenFromAuthStateSomehow()是一个我不知道怎么写的函数。

那么下一个问题是当这个请求因为访问令牌过期而失败时会发生什么。我想使用 ApolloonError从 API 捕获 401 错误并通过获取刷新的令牌重试请求:

const retryLink = onError(({ networkError }) => {
    if (networkError) {
        const newToken = getRefreshedToken()

        if (newToken) {
            retryRequest()
            setTokenInAuthStateSomehow(newToken)
        }
    }
})

但是我们遇到了同样的问题 - 现在我需要将新令牌发送authState即 React Context:setTokenInAuthStateSomehow()是一个我也不知道如何编写的函数。

所以,最重要的问题是:我如何在 Apollo Link 和 React Context 之间进行通信?我是否必须以某种方式设置一些侦听器或事件?我会喜欢任何信息或朝着正确的方向前进。

标签: reactjsjwtapollo-client

解决方案


推荐阅读