Аутентификация Аполлона с Гэтсби

Я пытаюсь реализовать рабочий процесс Аутентификация, официально описанный в Документы Apollo, как я делал раньше в других проектах, но на этот раз с использованием Гэтсби.

Идея кажется довольно простой. Необходимо создать / обновить 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>

и в другом Составная часть с чем-то вроде Статус (где, если залогинен, показывает x, иначе y):

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

Проблема

В этой конфигурации, когда логин получает data (значит, учетные данные в порядке), я сохраняю токен, полученный в localStorage, но компонент Статус выполняет Query с предыдущим (пустым) token, поэтому показывает выход из системы, а также делает что-то вроде history.push('/') после авторизоваться.

При обновлении страницы, поскольку элемент в localStorage был сохранен ранее, Статус отображается как зарегистрированный.

Ожидаемое поведение

Идея состоит в том, чтобы обновить компонент Статус после входа в систему, избегая обновления страницы, по этой причине я добавил refetchQueries = {[{ query: CURRENT_USER_QUERY }]}.

Я пробовал некоторые вещи, например, передать props (не нужно, если я изменю route и использую withRouter в компоненте Статус), но, похоже, поздно, Query был запущен без нового token.

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
1
0
1 004
2

Ответы 2

Основная проблема здесь, вероятно, в том, что ваш компонент Статус необходимо повторно визуализировать только после того, как токен будет сохранен в localStorage. Сейчас, наверное, слишком рано делать рендеринг.

Вы можете попробовать обернуть свой компонент Статус другим компонентом оболочки и проверить наличие токена перед рендерингом компонента Статус.

Спасибо, Энди за ответ, я попробовал то, что ты сказал, но проблема не устранена. Итак, после входа в систему console.infoging элемент localStorage в компоненте Статус кажется установленным, поэтому я условно визуализирую компонент <Query>, но кажется, что запрос, отправленный на сервер, не имеет токена.

Lionel T 01.06.2018 10:23

Я считаю, что ваша проблема связана с тем, как определяются ссылки. IMO, AuthLink должен быть определен перед HttpLink (как промежуточное ПО):

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

Хотя в документации сказано, что concat и from делают одно и то же, порядок важен. Вы хотите установить контекст перед отправкой запроса.

похоже, что проблема связана с Аполлон. Вот три открытых вопроса, которые расширяют ситуацию: 2009 г., 630 и 461.

Lionel T 01.06.2018 16:47

Другие вопросы по теме