Gatsby的Apollo身份验证

时间:2018-05-30 21:25:21

标签: reactjs apollo react-apollo apollo-client gatsby

我正在尝试实现Apollo docs中正式描述的身份验证工作流,就像我之前在其他项目中所做的那样,但这次使用 Gatsby

这个想法似乎很简单。需要创建/更新gatsby-browser.js,例如在使用redux时,但要初始化ApolloClient并通过ApolloProvider

类似的东西:

import React from 'react'
import { Router } from 'react-router-dom'
import { ApolloProvider } from 'react-apollo'
import { ApolloClient } from 'apollo-client'
import { createHttpLink } from 'apollo-link-http'
import { InMemoryCache } from 'apollo-cache-inmemory'
import { setContext } from 'apollo-link-context'

const httpLink = createHttpLink({
  uri: process.env.ENDPOINT_URI,
  credentials: 'same-origin',     
})

const authLink = setContext((_, { headers }) => {
  const token = localStorage.getItem('token');
  return {
    headers: {
      ...headers,
      authorization: token ? `Bearer ${token}` : "",
    }
  }
})

const client = new ApolloClient({
  link: authLink.concat(httpLink),
  cache: new InMemoryCache().restore({}),
})

exports.replaceRouterComponent = ({ history }) => {
  const ConnectedRouterWrapper = ({ children }) => (
    <ApolloProvider client={client}>
      <Router history={history}>{children}</Router>
    </ApolloProvider>
  )

  return ConnectedRouterWrapper
}

然后使用

登录
<Mutation
  mutation={LOGIN_MUTATION}
  refetchQueries={[{ query: CURRENT_USER_QUERY }]}
>
  {/*...*/}
</Mutation>

和另一个组件中的状态(其中,如果登录则显示x,否则为y):

<Query query={CURRENT_USER_QUERY} fetchPolicy="network-only">
{/*...*/}
</Query>

问题

使用此配置,当登录收到data(因此,凭据正常)时,我保存在localStorage中收到的令牌,但状态组件执行{{ 1}}使用上一个(空)Query,因此显示已注销,登录后也会执行类似token的操作。

刷新页面,因为history.push('/')中的项目之前已保存,状态显示为已登录。

预期行为

我的想法是在登录后更新 Status 组件,避免刷新页面,因此我添加了localStorage

我尝试了一些诸如传递refetchQueries={[{ query: CURRENT_USER_QUERY }]}之类的内容(如果我更改props并在状态组件中使用route则不需要),但似乎迟到,withRouter在没有新Query的情况下被解雇。

2 个答案:

答案 0 :(得分:0)

这里的主要问题可能是您的状态组件只有在将令牌保存到localStorage后才需要重新呈现。现在它可能过早重新渲染。

您可以尝试使用其他包装器组件包装 Status 组件,并在呈现 Status 组件之前检查令牌是否存在。

答案 1 :(得分:0)

我认为您的问题与链接的定义方式有关。 IMO,AuthLink应该在HttpLink之前定义(作为中间件):

const client = new ApolloClient({
  link: ApolloLink.from([
    authLink,
    httpLink
  ]),
  cache: new InMemoryCache().restore({}),
})

虽然文档说concat和from做同样的事情,但顺序很重要。您希望在发送请求之前设置上下文。