Rooks
HooksState Management

usePromise

Tracks the status and result of a Promise (pending, resolved, or rejected).

About

Promise management hook for React that handles async operations with automatic loading, error, and data states.


Examples

Basic usage

import { usePromise } from "rooks";

async function loadGreeting() {
  return Promise.resolve("Hello from the promise");
}

export default function App() {
  const { data, loading, error } = usePromise(loadGreeting);

  if (loading) return <p role="status">Loading…</p>;
  if (error) return <p role="alert">Error: {error.message}</p>;
  return <p>{data}</p>;
}

With dependencies

import React, { useState } from "react";
import { usePromise } from "rooks";

function fetchUserPosts(userId) {
  return fetch(`/api/users/${userId}/posts`).then((res) => res.json());
}

export default function App() {
  const [userId, setUserId] = useState(1);

  const {
    data: posts,
    loading,
    error,
  } = usePromise(
    () => fetchUserPosts(userId),
    [userId] // Re-fetch when userId changes
  );

  return (
    <div>
      <button onClick={() => setUserId(userId + 1)}>
        Load User {userId + 1} Posts
      </button>

      {loading && <div>Loading posts...</div>}
      {error && <div>Error: {error.message}</div>}

      {posts && (
        <ul>
          {posts.map((post) => (
            <li key={post.id}>{post.title}</li>
          ))}
        </ul>
      )}
    </div>
  );
}

Error handling

import React, { useState } from "react";
import { usePromise } from "rooks";

function fetchData(shouldFail = false) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (shouldFail) {
        reject(new Error("Network request failed"));
      } else {
        resolve({ message: "Data loaded successfully!" });
      }
    }, 1000);
  });
}

export default function App() {
  const [shouldFail, setShouldFail] = useState(false);

  const { data, loading, error } = usePromise(
    () => fetchData(shouldFail),
    [shouldFail]
  );

  return (
    <div>
      <button onClick={() => setShouldFail(!shouldFail)}>
        Toggle Error: {shouldFail ? "Will Fail" : "Will Succeed"}
      </button>

      {loading && <div>Loading...</div>}
      {error && (
        <div style={{ color: "red" }}>Error occurred: {error.message}</div>
      )}
      {data && <div style={{ color: "green" }}>{data.message}</div>}
    </div>
  );
}

Parameters

ArgumentTypeDescriptionDefault value
asyncFunctionfunctionAsync function that returns a Promise-
depsarrayDependency array for re-running the promise[]

Return value

Return valueTypeDescription
stateObjectObject containing {data: T | null, loading: boolean, error: Error | null}

Behavior and lifecycle

The async function runs after commit and runs again when its stable wrapper or a listed dependency changes. Fulfillment sets { data, loading: false, error: null }; rejection is normalized to an Error and clears data. Cleanup prevents a settled promise from updating state after that effect is replaced or unmounted, but it does not cancel the underlying work. The current implementation does not reset loading to true when dependencies trigger a later run.

Compatibility and accessibility

The hook starts work only in an effect, so server output contains the initial { data: null, loading: true, error: null } state. Use role="status" for loading feedback and role="alert" for errors when those updates should be announced.

On this page