初始化后更新 ApolloClient headers

Update ApolloClient headers after it was initialised

我的应用程序包含 <Apollo /> 组件,该组件实质上是初始化客户端。

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

进一步,用户可以执行某些操作,这需要我为以前不存在的 apollo 客户端设置一些新的 headers。我最初想为此使用反应上下文来传递 set new headers 并在 <Apollo /> 中使用它们,但我不确定这是否是正确的方法。

看了文档,好像apollo headers只能在初始化的时候设置?

您通常不想将 header 直接传递给您的 Apollo 客户端实例,而是希望利用 apollo-link-context。您可以将实际的 header 值存储在内存、LocalStorage 或任何对您的应用程序有意义的地方。然后在发送之前使用 link 将它们注入到每个请求中:

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可以异步。您传递给它的函数应该 return 一个带有您想要更改的任何上下文字段的 object,或者一个将解析为一个的 Promise:

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

您可以查看 the docs 以获取更多示例。

丹尼尔·里尔登是对的。然而,对于 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;

Migrating to Apollo Client 3.0 (docs)

为了扩展 Daniel Rearden 的回答,如果您只想为特定的 query/mutation 添加 headers 而不是所有后续查询:

初始化阿波罗:

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()
});

然后简单地将上下文添加到所需的 query/mutation 本身:

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