Skip to content

Async Hooks

useCancelableAsyncTaskCallback

Create cancelable async task callback.

tsx
import { useCancelableAsyncTaskCallback } from '@outilx/react-hooks';

function Component() {
  const fetchData = useCancelableAsyncTaskCallback(async (signal) => {
    const response = await fetch('/api/data', { signal });
    return response.json();
  });
  
  const handleClick = async () => {
    try {
      const data = await fetchData();
      console.log(data);
    } catch (error) {
      if (error.name === 'AbortError') {
        console.log('Request was cancelled');
      }
    }
  };
  
  return (
    <button onClick={handleClick}>
      Fetch Data
    </button>
  );
}

useTaskPending

Wrap an async task with pending state tracking.

tsx
import { useTaskPending } from '@outilx/react-hooks';

function DataFetcher() {
  const fetchData = async () => {
    const response = await fetch('/api/data');
    return response.json();
  };
  
  const [loadData, isPending] = useTaskPending(fetchData);
  
  return (
    <div>
      <button onClick={loadData} disabled={isPending}>
        {isPending ? 'Loading...' : 'Load Data'}
      </button>
    </div>
  );
}

useTaskPendingState

Wrap an async task with pending state and store the result.

tsx
import { useTaskPendingState } from '@outilx/react-hooks';
import { useState } from 'react';

function UserList() {
  const [users, setUsers] = useState([]);
  
  const fetchUsers = async () => {
    const response = await fetch('/api/users');
    return response.json();
  };
  
  const [loadUsers, isPending] = useTaskPendingState(fetchUsers, setUsers);
  
  return (
    <div>
      <button onClick={loadUsers} disabled={isPending}>
        {isPending ? 'Loading...' : 'Load Users'}
      </button>
      <ul>
        {users.map(user => <li key={user.id}>{user.name}</li>)}
      </ul>
    </div>
  );
}

Combining with useArray

A powerful pattern is to combine useTaskPendingState with useArray:

tsx
import { useArray, useTaskPendingState } from '@outilx/react-hooks';

function UserManager() {
  const [users, { push, removeById, set }] = useArray([]);
  
  const fetchUsers = async () => {
    const response = await fetch('/api/users');
    return response.json();
  };
  
  const [loadUsers, isPending] = useTaskPendingState(fetchUsers, set);
  
  return (
    <div>
      <button onClick={loadUsers} disabled={isPending}>
        {isPending ? 'Loading...' : 'Load Users'}
      </button>
      <button onClick={() => push({ id: Date.now(), name: 'New User' })}>
        Add User
      </button>
      <ul>
        {users.map(user => (
          <li key={user.id}>
            {user.name}
            <button onClick={() => removeById(user.id)}>Delete</button>
          </li>
        ))}
      </ul>
    </div>
  );
}