创建Client后(登录后)将Context Link 添加到Apollo Link

Add Context Link to Apollo Link after Client is created (after log-in)

我想将上下文 Link 添加到现有客户的 Apollo Link 链中。

这是我通读过的两个 GitHub 期:First, Second

我不想使用本地存储来存储令牌,如文档所示 here

我有一个用于存储我的令牌的身份验证提供程序。存储我的令牌后,我想将上下文 Link 添加到 Apollo 客户端的 links

  const authLink = setContext((_, { headers }) => {
    const newHeaders = { ...headers };
    if (token) newHeaders.authorization = `Bearer ${token}`;

    return {
      headers: newHeaders,
    };
  });

我知道我可以通过 useClient 访问客户端。 如何在创建客户端之前将此 link 添加到我的组件中已经存在的客户端?

link: authLink.concat(httpLink)link: authLink.concat(whateverLinksApolloHas)

我不相信有支持的方式来做你想做的事情。您 可以 做的是初始化 ApolloClient 的新实例并将其传递给 ApolloProvider。例如:

const [token, setToken] = useState(null)
const client = getClient(token) // adds the appropriate links as necessary

return <ApolloProvider client={client}><App/></ApolloProvider>

如果您走这条路并且需要在令牌更改时保留缓存,请确保每次创建客户端时都使用相同的 InMemoryCache 实例。

然而,即使这样也可能有点矫枉过正。没有理由不能总是使用 setContext。在修改 headers.

之前,您已经在检查令牌是否存在

从 Apollo Client v3.0.0 开始,您现在可以在创建 Apollo Client (see Changelog Section v3) 后使用 setLink 方法更新 link 链。

Apollo Client now supports setting a new ApolloLink (or link chain) after new ApolloClient() has been called, using the ApolloClient#setLink method. @hwillson in #6193

但是,除此之外,我还没有找到任何关于它的文档。

我无法使用 setContext 添加上下文 link。相反,它看起来像是取代了整个 link 链,所以这是我使用 @apollo/client@3.2.5.

的解决方案
import { ApolloClient, HttpLink, NormalizedCacheObject } from '@apollo/client/core';
import { setContext } from '@apollo/client/link/context';
import fetchNewToken from 'your-token-function-file'

const replaceLinkChainOnClient = (client: ApolloClient<NormalizedCacheObject>, url: string) => {
    const httpLink: HttpLink = new HttpLink({
        uri: url
    });

    const link = setContext(async (operation, prevContext) => {
        const token = await fetchNewToken();
        return {
            ...prevContext,
            headers: {
                ...prevContext.headers,
                Authorization: `Bearer ${token}`
            }
        };
    });
    client.setLink(link.concat(httpLink));
};