# How to Handle Response Data and Errors in a POST Request with Axios in React

> Master Axios POST requests in React. Learn to manage response data and errors with useState and useCallback. Implement robust error handling for a better user experience.

- Repository: [Meta/react](https://github.com/facebook/react)
- Tags: how-to-guide
- Published: 2026-02-18

---

**Use React's `useState` hook to track loading, data, and error states, wrap your Axios POST logic in `useCallback` for stable memoization, and implement granular error handling by inspecting `error.response`, `error.request`, and `error.message` to provide specific UI feedback.**

When building modern React applications, handling a POST request with Axios in React requires more than just firing off an API call. According to the facebook/react source code, the framework provides specific hooks—implemented in [`packages/react/src/ReactHooks.js`](https://github.com/facebook/react/blob/main/packages/react/src/ReactHooks.js)—that enable predictable state management for asynchronous operations. Mastering the interaction between Axios error objects and React's state lifecycle ensures your components remain stable while providing clear feedback for network failures, validation errors, and successful submissions.

## Core React Hooks for POST Request State Management

React's hook API provides the building blocks for managing asynchronous POST requests. According to the facebook/react repository, these primitives are defined in [`packages/react/src/ReactHooks.js`](https://github.com/facebook/react/blob/main/packages/react/src/ReactHooks.js) and implemented in [`packages/react-reconciler/src/ReactFiberHooks.js`](https://github.com/facebook/react/blob/main/packages/react-reconciler/src/ReactFiberHooks.js).

| Hook | Purpose | Source Location |
|------|---------|-----------------|
| `useState` | Creates local state for data, loading flags, and error objects. | [`packages/react/src/ReactHooks.js`](https://github.com/facebook/react/blob/main/packages/react/src/ReactHooks.js) (line 66) |
| `useEffect` | Optionally runs the request automatically when dependencies change. | [`packages/react/src/ReactHooks.js`](https://github.com/facebook/react/blob/main/packages/react/src/ReactHooks.js) (line 87) |
| `useCallback` | Memoizes the request function to avoid unnecessary re-creations inside renders. | [`packages/react/src/ReactHooks.js`](https://github.com/facebook/react/blob/main/packages/react/src/ReactHooks.js) (line 118) |

These hooks work together to create a predictable data flow. The `useCallback` hook is particularly important for POST requests triggered by user interactions, as it prevents the creation of new function references on every render, which could cause unnecessary effect re-runs or child component re-renders.

## Step-by-Step Pattern for Axios POST Handling

Implementing a robust POST request with Axios in React follows a consistent four-phase pattern that leverages React's state management capabilities.

### Initialize Component State

Begin by declaring state variables to track the request lifecycle. This separation of concerns allows the UI to react distinctly to loading, success, and error conditions.

```javascript
const [data, setData] = useState(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);

```

### Create the Request Handler with useCallback

Wrap the Axios logic in `useCallback` to maintain a stable function reference. This handler should manage the loading state, execute the POST request, and handle the response or error accordingly.

```javascript
const postData = useCallback(async (payload) => {
  setLoading(true);
  setError(null);
  try {
    const response = await axios.post('/api/endpoint', payload);
    setData(response.data);
  } catch (err) {
    // Error handling logic will be detailed in the next section
    handleAxiosError(err);
  } finally {
    setLoading(false);
  }
}, []);

```

### Trigger the POST Request

Invoke the memoized handler based on your component's requirements. For user-initiated actions like form submissions, call the function inside an event handler.

```javascript
const handleSubmit = (e) => {
  e.preventDefault();
  postData({ name, email });
};

```

For automatic data fetching when the component mounts, use `useEffect` with an empty dependency array.

```javascript
useEffect(() => {
  postData(initialPayload);
}, [postData]);

```

### Render UI Based on State

Update the JSX to reflect the current request status, providing clear visual feedback for each state.

```jsx
return (
  <div>
    {loading && <p>Sending…</p>}
    {error && <p className="error">{error.message}</p>}
    {data && <pre>{JSON.stringify(data, null, 2)}</pre>}
  </div>
);

```

## Understanding Axios Error Objects in React

Effective error handling requires inspecting the specific properties of Axios error objects. When a POST request fails, Axios populates distinct fields that indicate where the failure occurred.

**`error.response`**: Present when the server responds with a status code outside the 2xx range. Contains the HTTP status, headers, and response body.

**`error.request`**: Present when the request was transmitted but no response was received, typically indicating network connectivity issues or server downtime.

**`error.message`**: Contains a generic error message when the request setup itself failed before transmission.

Implement granular error handling by checking these properties in sequence:

```javascript
const handleAxiosError = (err) => {
  if (err.response) {
    // Server responded with error status (4xx, 5xx)
    setError({
      status: err.response.status,
      message: err.response.data?.message || 'Server error occurred'
    });
  } else if (err.request) {
    // Request made but no response received
    setError({ message: 'Network error – no response from server' });
  } else {
    // Error in request configuration
    setError({ message: err.message });
  }
};

```

## Complete Code Examples for POST Requests with Axios

The following production-ready components demonstrate the complete pattern for handling POST requests with Axios in React, including the state management logic defined in [`packages/react/src/ReactHooks.js`](https://github.com/facebook/react/blob/main/packages/react/src/ReactHooks.js).

### Form-Driven POST Request Component

This example implements a contact form that posts data to an API endpoint when submitted, utilizing `useCallback` to prevent unnecessary function recreation.

```jsx
import React, { useState, useCallback } from 'react';
import axios from 'axios';

export default function ContactForm() {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);
  const [name, setName] = useState('');
  const [email, setEmail] = useState('');

  const postData = useCallback(async (payload) => {
    setLoading(true);
    setError(null);
    try {
      const response = await axios.post('/api/contact', payload);
      setData(response.data);
    } catch (err) {
      if (err.response) {
        setError({
          status: err.response.status,
          message: err.response.data?.msg || 'Server validation failed'
        });
      } else if (err.request) {
        setError({ message: 'Network error – no response from server' });
      } else {
        setError({ message: err.message });
      }
    } finally {
      setLoading(false);
    }
  }, []);

  const handleSubmit = (e) => {
    e.preventDefault();
    postData({ name, email });
  };

  return (
    <form onSubmit={handleSubmit}>
      {loading && <p>Sending…</p>}
      {error && <p className="error">{error.message}</p>}
      {data && <p>Thank you! Confirmation ID: {data.id}</p>}

      <input 
        value={name} 
        onChange={e => setName(e.target.value)} 
        placeholder="Name" 
        required 
      />
      <input 
        value={email} 
        onChange={e => setEmail(e.target.value)} 
        placeholder="Email" 
        required 
      />
      <button type="submit" disabled={loading}>
        Submit
      </button>
    </form>
  );
}

```

### Automatic POST on Component Mount

This pattern uses `useEffect` to trigger a POST request immediately when the component mounts, useful for analytics or initial data synchronization.

```jsx
import React, { useState, useEffect, useCallback } from 'react';
import axios from 'axios';

export default function Dashboard() {
  const [stats, setStats] = useState(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  const fetchStats = useCallback(async () => {
    setLoading(true);
    setError(null);
    try {
      const { data } = await axios.post('/api/dashboard', { range: '30d' });
      setStats(data);
    } catch (err) {
      setError(err.response?.data?.msg || err.message);
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => {
    fetchStats();
  }, [fetchStats]);

  if (loading) return <p>Loading dashboard…</p>;
  if (error) return <p className="error">{error}</p>;
  if (!stats) return null;

  return (
    <div>
      <h2>30‑Day Overview</h2>
      <pre>{JSON.stringify(stats, null, 2)}</pre>
    </div>
  );
}

```

## Summary

Handling a POST request with Axios in React effectively requires combining the library's error normalization with React's state management primitives.

- **Use `useState`** to maintain separate variables for `data`, `loading`, and `error` states, enabling precise UI feedback.
- **Wrap handlers in `useCallback`** to prevent function recreation on every render, as implemented in [`packages/react/src/ReactHooks.js`](https://github.com/facebook/react/blob/main/packages/react/src/ReactHooks.js).
- **Inspect Axios error properties** (`err.response`, `err.request`, `err.message`) to distinguish between server errors, network failures, and client configuration issues.
- **Leverage `useEffect`** only when automatic execution on mount is required; otherwise, prefer event handlers for user-initiated POST requests.

## Frequently Asked Questions

### How do I prevent memory leaks when the component unmounts during a POST request?

To prevent memory leaks, implement an `isMounted` flag or use an `AbortController` to cancel the Axios request. Inside `useEffect`, return a cleanup function that sets the flag to false or calls `controller.abort()`. This ensures that state updates in the `finally` block or `.then()` callbacks do not attempt to update an unmounted component, which would trigger React warnings according to the reconciliation logic in [`packages/react-reconciler/src/ReactFiberHooks.js`](https://github.com/facebook/react/blob/main/packages/react-reconciler/src/ReactFiberHooks.js).

### Should I use useEffect or event handlers for POST requests in React?

**Use event handlers** for user-initiated actions like form submissions or button clicks, as this gives the user explicit control over when data is sent. **Use `useEffect`** only when the POST request must execute automatically based on component lifecycle events or dependency changes, such as logging analytics on mount or syncing data when an ID parameter changes. Avoid putting POST requests in `useEffect` without careful dependency management to prevent infinite loops or unintended duplicate requests.

### How do I handle validation errors returned from the server?

Server validation errors typically return HTTP 400 or 422 status codes with error details in the response body. Access these through `err.response.data` after checking that `err.response` exists. Extract specific field errors or general messages and update your component's error state to display them adjacent to relevant form fields or in a global alert banner. This approach leverages Axios's automatic JSON parsing and React's state updates to provide immediate user feedback.

### Is useCallback necessary for Axios POST handlers?

While not strictly mandatory, **`useCallback` is strongly recommended** for Axios POST handlers, especially when passing the function to child components or including it in `useEffect` dependency arrays. Without `useCallback`, a new function reference is created on every render, potentially triggering unnecessary re-renders of optimized child components or causing `useEffect` to re-run unexpectedly. The implementation in [`packages/react/src/ReactHooks.js`](https://github.com/facebook/react/blob/main/packages/react/src/ReactHooks.js) ensures that `useCallback` maintains referential equality when dependencies remain unchanged, optimizing performance in components with frequent updates.