Beautiful Error Handling with Tanstack Query and Axios (The best combo??)

Published: (December 11, 2025 at 03:44 PM EST)
3 min read
Source: Dev.to

Source: Dev.to

The Backend Services

We have a very simple architecture for this project.

  • Supabase as BaaS handles authentication, session management, etc.
  • Express handles authorization, database querying, and other backend services.

For Express we employ a simplified MVC architecture:

  • Models – handle all database operations with Supabase.
  • Views – service classes in the front‑end.
  • Controllers – contain business logic.

We just use these names to ensure structure and separation of concerns.

Example Controller

export const completeProfile = async (req, res) => {
  try {
    const { role, userData } = req.body;

    const existingProfile = await UserProfileModel.getCustomerProfile(req.user.id);

    if (existingProfile) {
      return res.status(400).json({
        error: "ProfileError",
        message: "Profile already exists",
      });
    }

    const result = await UserProfileModel.createProfileWithEntity(
      req.user.id,
      role,
      userData
    );

    res.json({
      message: "Profile completed successfully",
      role,
      userId: req.user.id,
    });
  } catch (error) {
    res.status(500).json({
      error: "ProfileError",
      message: error.message,
    });
  }
};

When a user tries to create a profile that already exists, the controller returns a 400 response:

{
  "error": "ProfileError",
  "message": "Profile already exists"
}

The Good Part: Axios

Axios is a promise‑based HTTP client that simplifies API requests compared to the native fetch API.

Using fetch

const completeProfile = async (payload) => {
  const res = await fetch('/profile/complete', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(payload),
  });

  if (!res.ok) {
    const errorData = await res.json().catch(() => ({}));
    throw new Error(errorData.message || 'Failed to complete profile');
  }

  return res.json();
};

Using Axios

import axios from 'axios';

const completeProfile = async (payload) => {
  const { data } = await axios.post('/profile/complete', payload);
  return data;
};

Axios Error Object

When the response status is outside the 2xx range, Axios throws an error object like:

{
  "response": {
    "status": 400,
    "data": {
      "error": "ProfileError",
      "message": "Profile already exists"
    }
  }
}

This eliminates the need for manual if (!res.ok) checks.

TanStack Query (formerly React Query)

Instead of handling errors with try / catch in every component, TanStack Query centralizes data fetching, caching, loading states, and error handling.

What Is TanStack Query?

TanStack Query is a powerful data‑fetching and state‑management library for React. It automatically manages:

  • Loading states
  • Error handling
  • Retries and caching
  • Background refetching

This lets you focus on building features rather than wiring boilerplate.

Using TanStack Query with Axios

import { useMutation } from '@tanstack/react-query';

const useCompleteProfile = () => {
  return useMutation({
    mutationFn: (payload) => completeProfile(payload),
  });
};

Handling Errors in a Component

import { View, Text } from 'react-native';
import { useCompleteProfile } from './hooks';

const CompleteProfileComponent = ({ payload }) => {
  const mutation = useCompleteProfile();

  const handleSubmit = () => {
    mutation.mutate(payload);
  };

  return (
    <View>
      {/* ...your form UI... */}

      {mutation.isError && (
        <Text>
          {mutation.error?.response?.data?.message || 'An error occurred'}
        </Text>
      )}
    </View>
  );
};

The mutation.isError flag becomes true automatically when Axios throws an error, and the error details are accessible via mutation.error.

Images

Backend Architecture

Project Overview

Axios vs Fetch

Back to Blog

Related posts

Read more »

Under the hood: React

Introduction I've wanted to do this since the moment I started using React: understand what makes it tick. This is not a granular review of the source code. In...

React using Calculator

Today i completed one of the pratice project on React Using calculator.This React Calculator application performs basic arithmetic operations. It supports butto...