【问题标题】:Apollo Authentication with GatsbyGatsby 的 Apollo 身份验证
【发布时间】:2018-11-09 19:59:34
【问题描述】:

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

这个想法似乎很简单。需要像使用redux 时一样创建/更新gatsby-browser.js,但要初始化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>

在另一个 Component 中带有类似 Status 的内容(如果已登录,则显示 x,否则为 y):

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

问题

使用此配置,当登录接收到data(因此,凭据没问题)时,我将收到的令牌保存在localStorageStatus 组件使用前面的Query (空)token,所以显示已注销,登录后也会执行history.push('/') 之类的操作。

刷新页面,由于localStorage中的项目之前保存过,状态显示为已登录。

预期行为

这个想法是在登录后更新 Status 组件以避免刷新页面,为此我添加了refetchQueries={[{ query: CURRENT_USER_QUERY }]}

我尝试了一些方法,例如通过 props(如果我更改 route 并在 Status 组件中使用 withRouter,则不需要),但似乎迟到了,Query在没有新的token 的情况下被解雇。

【问题讨论】:

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


    【解决方案1】:

    这里的主要问题可能是您的 Status 组件只有在令牌保存到localStorage 之后才需要重新渲染。现在重新渲染可能为时过早。

    您可以尝试用另一个包装器组件包装您的 Status 组件,并在渲染 Status 组件之前检查令牌是否存在。

    【讨论】:

    • 感谢安迪的回复,我试过你说的,但问题仍然存在。所以,登录后,Status 组件中的console.logging localStorage 项似乎已设置,所以我有条件地渲染了 组件,但似乎发送到服务器的请求没有令牌。
    【解决方案2】:

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

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

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

    【讨论】:

    • 似乎该问题与 Apollo 有关。以下是扩大情况的三个未解决问题:2009630461
    猜你喜欢
    • 2019-02-25
    • 2018-05-23
    • 2020-08-17
    • 1970-01-01
    • 2020-10-22
    • 2018-06-22
    • 2018-08-18
    • 2021-10-03
    • 2019-02-28
    相关资源
    最近更新 更多