How to Use Axios with GraphQL APIs

Using Axios to interact with GraphQL endpoints is a lightweight alternative to dedicated GraphQL clients like Apollo Client or Relay. Because GraphQL operates primarily over HTTP using standard POST requests, Axios can seamlessly send queries, mutations, and variables by transmitting a structured JSON payload to the server. This guide covers how to set up Axios for GraphQL, execute queries and mutations, pass dynamic variables, and handle GraphQL-specific response structures and errors.

The Anatomy of a GraphQL Request in Axios

GraphQL servers typically expose a single HTTP POST endpoint (e.g., /graphql). The request body must be a JSON object containing at least a query field as a string. Optionally, it can include a variables field containing dynamic values.

Making a Basic Query

To fetch data, define your GraphQL query string and send it inside the request body using axios.post():

import axios from 'axios';

const fetchUserData = async () => {
  const endpoint = 'https://api.example.com/graphql';
  
  const query = `
    query GetUser {
      user(id: "123") {
        id
        name
        email
      }
    }
  `;

  try {
    const response = await axios.post(
      endpoint,
      { query },
      {
        headers: {
          'Content-Type': 'application/json',
        },
      }
    );

    console.log(response.data.data.user);
  } catch (error) {
    console.error('Network Error:', error);
  }
};

Using Dynamic Variables

Hardcoding values into query strings can lead to injection issues and poor reusability. Pass dynamic parameters using GraphQL variables and include a variables object alongside the query in the Axios payload.

const fetchUserWithVariables = async (userId) => {
  const endpoint = 'https://api.example.com/graphql';

  const query = `
    query GetUser($id: ID!) {
      user(id: $id) {
        id
        name
        email
      }
    }
  `;

  const variables = {
    id: userId,
  };

  const response = await axios.post(endpoint, {
    query,
    variables,
  });

  return response.data.data.user;
};

Executing Mutations

Mutations modify data on the server and follow the exact same HTTP transport structure as queries. The mutation string is passed in the query field of the request payload.

const createUser = async (name, email) => {
  const endpoint = 'https://api.example.com/graphql';

  const mutation = `
    mutation CreateUser($name: String!, $email: String!) {
      createUser(input: { name: $name, email: $email }) {
        id
        name
        email
      }
    }
  `;

  const variables = {
    name,
    email,
  };

  const response = await axios.post(endpoint, {
    query: mutation,
    variables,
  });

  return response.data.data.createUser;
};

Creating a Reusable Axios Instance

To avoid repeating the endpoint URL and authorization headers in every call, create a dedicated Axios instance:

import axios from 'axios';

const graphqlClient = axios.create({
  baseURL: 'https://api.example.com/graphql',
  headers: {
    'Content-Type': 'application/json',
    Authorization: 'Bearer YOUR_AUTH_TOKEN',
  },
});

export const executeGraphQL = async (query, variables = {}) => {
  const response = await graphqlClient.post('', {
    query,
    variables,
  });

  if (response.data.errors) {
    throw new Error(JSON.stringify(response.data.errors));
  }

  return response.data.data;
};

Handling GraphQL Errors

GraphQL handles errors differently than standard REST APIs:

  1. HTTP-Level Errors (4xx, 5xx): Occur during network failures or server outages, caught in the standard Axios catch block.
  2. GraphQL-Level Errors (200 OK with errors array): When a syntax or execution error occurs within GraphQL, the HTTP status is still usually 200 OK. The payload returns an errors array alongside or instead of the data object.

Always check for response.data.errors to ensure query execution succeeded:

const handleRequest = async (query, variables) => {
  try {
    const response = await axios.post('/graphql', { query, variables });

    if (response.data.errors) {
      console.error('GraphQL Errors:', response.data.errors);
      return null;
    }

    return response.data.data;
  } catch (httpError) {
    console.error('HTTP Request Failed:', httpError.message);
  }
};