【发布时间】:2021-07-26 09:36:53
【问题描述】:
我有一个具有以下顶级结构的 React SPA。我使用 Auth0 进行身份验证,使用 Apollo Client 进行查询,使用 React Context 提供全局状态。
我遇到的问题是,在 Apollo 客户端完成其标头的配置(即,通过 Auth0 插入令牌)之前,在我的全局状态下执行的查询正在执行。
有没有办法(也许使用 useApolloClient 钩子来判断 Apollo 在其 authLink 中是否有令牌?或者另一种方式来实现延迟初始化 Global State 直到其父组件 AuthorizedApolloProvider 完成的目标?
<BrowserRouter>
<Auth0ProviderWithHistory>
<AuthorizedApolloProvider>
<GlobalState>
<App />
</GlobalState>
</AuthorizedApolloProvider>
</Auth0ProviderWithHistory>
</BrowserRouter>
在 AuthorizedApolloProvider 中,我通过在所有查询中插入令牌来为 Apollo 设置上下文,如下所示:
const AuthorizedApolloProvider = ({children}) => {
const { getAccessTokenSilently } = useAuth0()
const httpLink = createHttpLink ({
uri: uriGQL, // a config parameter
})
const authLink = setContext(async () => {
const token = await getAccessTokenSilently()
console.log('Got the token..... ', token.substring(0, 10))
return {
headers: {
authorization: token ? token : ""
}
}
})
let links = [authLink, httpLink]
const client = new ApolloClient({
link: ApolloLink.from(links),
cache: new InMemoryCache({
addTypename: false,
}),
})
console.log('Rendering ApolloProvider')
return(
<ApolloProvider client={client}>
{children}
</ApolloProvider>
)
}
接下来,在 Global State 中,我发送 GQL 查询以获取有关已登录用户的信息,如下所示:
const GlobalState = props => {
const { user: auth0User, isLoading, isAuthenticated } = useAuth0()
const client = useApolloClient()
const [state, setState] = useState(initialState)
const [ getUser, { loading, data, error }] = useLazyQuery(GET_USER)
const history = useHistory()
useEffect(async () => {
// Has useAuth0 returned?
if(isLoading===false) {
console.log('isAuthenticated=', isAuthenticated)
console.log('auth0User', auth0User)
// Is authenticated?
if(!isAuthenticated) {
// If not authenticated...
console.log('Not authenticated')
localStorage.removeItem('user')
setState({ ...state, loaded: true, user: null })
}
else {
// If authenticated...
// Check to see if user object is in local storage
let user = await localStorage.getItem('user')
if(user) {
console.log('Authenticated, found user in local storage')
// User found in local storage
user = JSON.parse(user)
setState({ ...state, loaded: true, user: user })
}
else {
// User not found in local storage. Must fetch from server
console.log('Authenticated, getting user from server')
try {
console.log('Calling getUser...')
const result = await getUser()
}
catch (error) {
console.log(error)
}
}
}
}
}, [isLoading])
...
我遇到的问题是在 Apollo 客户端完成配置之前调用了 getUser 查询。
当我运行代码时,我看到下面的片段...
try {
console.log('Calling getUser...')
const result = await getUser()
}
...在以下...之前被执行
console.log('Got the token..... ', token.substring(0, 10))
return {
headers: {
authorization: token ? token : ""
}
}
【问题讨论】:
标签: auth0 apollo-client react-context