Обновите заголовки ApolloClient после его инициализации

Мое приложение обернуто компонентом <Apollo />, который, по сути, инициализирует клиент.

const client = new ApolloClient({
  link: new HttpLink({
    // ...
  }),
  cache: new InMemoryCache({
    // ..
  }),
});

В дальнейшем пользователи могут выполнить определенные действия, которые потребуют от меня установки нескольких новых заголовков для клиента apollo, которых раньше не было. Сначала я думал использовать реагирующий контекст, чтобы передать набор новых заголовков и использовать их внутри <Apollo />, но я не уверен, что это правильный способ сделать это.

После просмотра документов кажется, что заголовки apollo могут быть установлены только при его инициализации?

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

Ответы 3

Ответ принят как подходящий

Вместо того, чтобы передавать заголовки непосредственно вашему экземпляру клиента Apollo, вы обычно хотите использовать apollo-link-context. Вы можете хранить фактические значения заголовков в памяти, LocalStorage или в любом другом месте, имеющем смысл для вашего приложения. Затем используйте ссылку, чтобы вставить их в каждый запрос перед его отправкой:

const headerLink = setContext((request, previousContext) => ({
  headers: {
    // Make sure you include any existing headers!
    ...previousContext.headers,
    authorization: localStorage.getItem('authHeader')
  },
}));

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

setContext может быть асинхронным. Функция, которую вы ей передаете, должна возвращать либо объект с любыми контекстными полями, которые вы хотите изменить, либо обещание, которое разрешается в единицу:

const headerLink = setContext(async (request, previousContext) => {
  const authorization = await someAsyncCall()
  return {
    headers: {
      ...previousContext.headers,
      authorization,
    },
  }
});

Вы можете проверить документы для дополнительных примеров.

Но как вы обновляете его постфактум? Например, первоначальный запрос GraphQL на вход не имеет заголовка авторизации. После входа в систему как обновить экземпляр ApolloClient? Вы заменяете его новым новым ApolloClient?

DeltaTango 20.01.2021 23:04

Дэниел Реарден прав. Однако в Apollo 3 есть некоторые незначительные изменения, которые, как я обнаружил, еще недостаточно систематизированы в документации. Так что, возможно, это тоже поможет.

import React from 'react';
import { ApolloClient, InMemoryCache, HttpLink } from '@apollo/client';
import { setContext } from '@apollo/client/link/context';

function App() {

  const link = new HttpLink({ uri: process.env.REACT_APP_GRAPHQL_URI });

  const setAuthorizationLink = setContext((request, previousContext) => ({
    headers: {
      ...previousContext.headers,
      authorization: `Bearer ${ localStorage.getItem('auth_token') }`
    }
  }));

  const client = new ApolloClient({
    link: setAuthorizationLink.concat(link),
    cache: new InMemoryCache()
  });

  return (
    <ApolloProvider client = {client}>
      ...
    </ApolloProvider>
  );
}

export default App;

Переход на Apollo Client 3.0 (документы)

Как насчет примера входа? Первый запрос GraphQL, заголовок авторизации отсутствует. Как вы устанавливаете его после того, как ответ вернется? Как вы обновляете заголовки во время вашего приложения, а затем по цепочке?

DeltaTango 20.01.2021 23:05

Чтобы расширить ответ Даниэля Риардена, если вы хотите добавить заголовки только для определенного запроса/мутации, а не для всех последующих запросов:

Инициализировать Аполлона:

const httpLink = createHttpLink({
  uri: '/graphql',
});

const authLink = setContext((_, { headers }) => {
  // get the authentication token from local storage if it exists
  const token = localStorage.getItem('token');
  // return the headers to the context so httpLink can read them
  return {
    headers: {
      ...headers,
      authorization: token ? `Bearer ${token}` : "",
    }
  }
});

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

А затем просто добавьте контекст к самому желаемому запросу/мутации:

const {loading, data, error} = useQuery(QUERY_DEF, { 
    context:  {
        headers: {
            "HeaderKey": "HeaderValue"
        }
    }
});

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