Я пытаюсь реализовать рабочий процесс Аутентификация, официально описанный в Документы 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.





Основная проблема здесь, вероятно, в том, что ваш компонент Статус необходимо повторно визуализировать только после того, как токен будет сохранен в localStorage. Сейчас, наверное, слишком рано делать рендеринг.
Вы можете попробовать обернуть свой компонент Статус другим компонентом оболочки и проверить наличие токена перед рендерингом компонента Статус.
Я считаю, что ваша проблема связана с тем, как определяются ссылки. IMO, AuthLink должен быть определен перед HttpLink (как промежуточное ПО):
const client = new ApolloClient({
link: ApolloLink.from([
authLink,
httpLink
]),
cache: new InMemoryCache().restore({}),
})
Хотя в документации сказано, что concat и from делают одно и то же, порядок важен. Вы хотите установить контекст перед отправкой запроса.
Спасибо, Энди за ответ, я попробовал то, что ты сказал, но проблема не устранена. Итак, после входа в систему console.infoging элемент localStorage в компоненте Статус кажется установленным, поэтому я условно визуализирую компонент <Query>, но кажется, что запрос, отправленный на сервер, не имеет токена.