Мое приложение обернуто компонентом <Apollo />, который, по сути, инициализирует клиент.
const client = new ApolloClient({
link: new HttpLink({
// ...
}),
cache: new InMemoryCache({
// ..
}),
});
В дальнейшем пользователи могут выполнить определенные действия, которые потребуют от меня установки нескольких новых заголовков для клиента apollo, которых раньше не было. Сначала я думал использовать реагирующий контекст, чтобы передать набор новых заголовков и использовать их внутри <Apollo />, но я не уверен, что это правильный способ сделать это.
После просмотра документов кажется, что заголовки apollo могут быть установлены только при его инициализации?





Вместо того, чтобы передавать заголовки непосредственно вашему экземпляру клиента 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,
},
}
});
Вы можете проверить документы для дополнительных примеров.
Дэниел Реарден прав. Однако в 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, заголовок авторизации отсутствует. Как вы устанавливаете его после того, как ответ вернется? Как вы обновляете заголовки во время вашего приложения, а затем по цепочке?
Чтобы расширить ответ Даниэля Риардена, если вы хотите добавить заголовки только для определенного запроса/мутации, а не для всех последующих запросов:
Инициализировать Аполлона:
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"
}
}
});
Но как вы обновляете его постфактум? Например, первоначальный запрос GraphQL на вход не имеет заголовка авторизации. После входа в систему как обновить экземпляр ApolloClient? Вы заменяете его новым новым ApolloClient?