title: Communication between React Context and Apollo Client Link
body: <p>I am working on a single page webapp using React and Apollo Client, and I am wondering about how to correctly communicate authentication state between Apollo Client links and React context.</p>
  <p>Within the client, I have written an AuthProvider context that supplies the current user information, so that anywhere in the component tree I can do</p>
  <pre><code>const authState = useAuthState()
  const dispatch = useAuthDispatch()
  </code></pre>
  <p>and thus query and update the authentication information as I need.  I have used this, for example, to write a <code>PrivateRoute</code> component that redirects the viewer if she is not authenticated:</p>
  <pre><code>const PrivateRoute: FunctionComponent&lt;RouteProps&gt; = ({ children, ...rest }) =&gt; {
      const authState = useAuthState()
  
      return (
          &lt;Route
              {...rest}
              render={({ location }) =&gt;
                  authState.user ? (
                      children
                  ) : (
                      &lt;Redirect
                          to={{
                              pathname: &quot;/login&quot;,
                              state: { from: location }
                          }}
                      /&gt;
                  )
              }
          /&gt;
      )
  }
  </code></pre>
  <p>This is all fine. My issue arises when combining this with my chosen form of authentication, which is JWT. I am storing the access token in the <code>authState</code> and the refresh token is set as an httpOnly cookie by the back-end on login.</p>
  <p>But I have to send the access token as an <code>Authorization: Bearer</code> header on each request, which I want to do using an Apollo Link, as follows:</p>
  <pre><code>const authLink = setContext(async (_, { headers }) =&gt; {
      const token = getTokenFromAuthStateSomehow()
  
      return {
          headers: {
              ...headers,
              authorization: token ? `Bearer ${token}` : &quot;&quot;
          }
      }
  })
  </code></pre>
  <p>But this is within an Apollo Link, where I of course don't have direct access to the React Context. <code>getTokenFromAuthStateSomehow()</code> is a function I do not know how to write.</p>
  <p>Then the next issue is what happens when this request fails because the access token has expired. I want to use Apollo's <code>onError</code> to catch a 401 error from the API and retry the request by getting a refreshed token:</p>
  <pre><code>const retryLink = onError(({ networkError }) =&gt; {
      if (networkError) {
          const newToken = getRefreshedToken()
  
          if (newToken) {
              retryRequest()
              setTokenInAuthStateSomehow(newToken)
          }
      }
  })
  </code></pre>
  <p>But then we have the same problem - now I need to send the new token <em>back</em> to <code>authState</code>, i.e.  to React Context: <code>setTokenInAuthStateSomehow()</code> is a function I do not know how to write either.</p>
  <p>So, the overarching question is: how do I communicate between an Apollo Link and React Context? Do I have to setup some listeners or events somehow? I would love any information or push in the right direction.</p>