React relay auth middleware

Viewed 302

I am trying to build a react app using relay following instructions from the react-relay step by step guide. In the guide the auth token is stored in the env file, and I am trying to retrieve my token from memory which is created when the user logs in and is passed down to all components using the context API. I am not storing it in local storage and have a refresh token to automatically refresh the JWT.
From the tutorial, the relay environment class is not a React component because of which I cannot access the context object.
Is there a way to pass the token from my context to the relay environment class or any middleware implementation to accomplish this.
Any help is greatly appreciated.

import { useContext } from 'react';
import { Environment, Network, RecordSource, Store } from 'relay-runtime';
import axios from "axios";

import { AppConstants } from './app-constants';
import { AuthContext, AuthSteps } from "./context/auth-context";
import { useCookie } from './hooks/useCookie';

interface IGraphQLResponse {
    data: any;
    errors: any;
}

async function fetchRelay(params: { text: any; name: any; }, variables: any, _cacheConfig: any) {
    const authContext = useContext(AuthContext); //Error - cannot access context
    const { getCookie } = useCookie(); //Error - cannot access context

    axios.interceptors.request.use(
        (config) => {
            const accessToken = authContext && authContext.state && authContext.state.token;
            if(accessToken) config.headers.Authorization = `Bearer ${accessToken}`;
            return config;
        },
        (error) => {
            Promise.reject(error);
        }
    );

    
    axios.interceptors.response.use(
        (response) => {
            return response;
        },
        async (error) => {
            const originalRequest = error.config;
            const refreshToken = getCookie(AppConstants.AUTH_COOKIE_NAME);

            if(refreshToken && error.response.status === 401 && !originalRequest._retry) {
                originalRequest._retry = true;
                const response = await axios
                    .post(process.env.REACT_APP_REFRESH_TOKEN_API_URL!, { refreshToken: refreshToken });
                if (response.status === 200 && response.data && response.data.accessToken) {
                    authContext && authContext.dispatch && authContext.dispatch({
                        payload: {
                            token: response.data.accessToken
                        },
                        type: AuthSteps.SIGN_IN
                    });
                    accessToken = response.data.accessToken;
                    return axios(originalRequest);
                }
            }
            return Promise.reject(error);
        }
    );
    

    const data: IGraphQLResponse = await axios.post(process.env.REACT_APP_GRAPHQL_URL!, {
        query: params.text,
        variables
    });    

    if(Array.isArray(data.errors)) {
        throw new Error(
            `Error fetching GraphQL query '${
                params.name
            }' with variables '${JSON.stringify(variables)}': ${JSON.stringify(
                data.errors,
            )}`,
            );
    }
    return data;
}

export default new Environment({
    network: Network.create(fetchRelay),
    store: new Store(new RecordSource(), {
      gcReleaseBufferSize: 10,
    }),
});

0 Answers
Related