Skip to content

Data Fetching ​

This guide covers advanced data fetching patterns using Flowfull Clients.

useBridgeQuery ​

The useBridgeQuery hook uses SWR (stale-while-revalidate) for efficient data fetching with automatic caching and revalidation.

Basic Usage ​

typescript
import { useBridgeApi, useBridgeQuery } from '@pubflow/react';

function UserList() {
  const userService = useBridgeApi({ endpoint: 'users' });
  
  const { data, meta, isLoading, error, refetch } = useBridgeQuery(
    userService,
    'list',
    { page: 1, limit: 20 }
  );
  
  return (
    <div>
      {isLoading && <div>Loading...</div>}
      {error && <div>Error: {error.message}</div>}
      {data && (
        <ul>
          {data.map(user => (
            <li key={user.id}>{user.name}</li>
          ))}
        </ul>
      )}
    </div>
  );
}

Pagination ​

typescript
function PaginatedUserList() {
  const [page, setPage] = useState(1);
  const userService = useBridgeApi({ endpoint: 'users' });
  
  const { data, meta, isLoading } = useBridgeQuery(
    userService,
    'list',
    { page, limit: 10 }
  );
  
  return (
    <div>
      <ul>
        {data?.map(user => (
          <li key={user.id}>{user.name}</li>
        ))}
      </ul>
      <div>
        <button 
          onClick={() => setPage(p => p - 1)} 
          disabled={page === 1}
        >
          Previous
        </button>
        <span>Page {page} of {Math.ceil((meta?.total || 0) / 10)}</span>
        <button 
          onClick={() => setPage(p => p + 1)} 
          disabled={!meta?.hasMore}
        >
          Next
        </button>
      </div>
    </div>
  );
}

Sorting ​

typescript
function SortableUserList() {
  const [orderBy, setOrderBy] = useState('name');
  const [orderDir, setOrderDir] = useState<'asc' | 'desc'>('asc');
  const userService = useBridgeApi({ endpoint: 'users' });
  
  const { data, isLoading } = useBridgeQuery(
    userService,
    'list',
    { orderBy, orderDir, limit: 20 }
  );
  
  function toggleSort(field: string) {
    if (orderBy === field) {
      setOrderDir(orderDir === 'asc' ? 'desc' : 'asc');
    } else {
      setOrderBy(field);
      setOrderDir('asc');
    }
  }
  
  return (
    <table>
      <thead>
        <tr>
          <th onClick={() => toggleSort('name')}>
            Name {orderBy === 'name' && (orderDir === 'asc' ? '↑' : '↓')}
          </th>
          <th onClick={() => toggleSort('email')}>
            Email {orderBy === 'email' && (orderDir === 'asc' ? '↑' : '↓')}
          </th>
        </tr>
      </thead>
      <tbody>
        {data?.map(user => (
          <tr key={user.id}>
            <td>{user.name}</td>
            <td>{user.email}</td>
          </tr>
        ))}
      </tbody>
    </table>
  );
}
typescript
function SearchableUserList() {
  const [query, setQuery] = useState('');
  const [debouncedQuery, setDebouncedQuery] = useState('');
  const userService = useBridgeApi({ endpoint: 'users' });
  
  // Debounce search query
  useEffect(() => {
    const timer = setTimeout(() => {
      setDebouncedQuery(query);
    }, 300);
    
    return () => clearTimeout(timer);
  }, [query]);
  
  const { data, isLoading } = useBridgeQuery(
    userService,
    'search',
    { q: debouncedQuery, limit: 10 }
  );
  
  return (
    <div>
      <input
        value={query}
        onChange={(e) => setQuery(e.target.value)}
        placeholder="Search users..."
      />
      {isLoading && <div>Searching...</div>}
      <ul>
        {data?.map(user => (
          <li key={user.id}>{user.name}</li>
        ))}
      </ul>
    </div>
  );
}

useBridgeCrud ​

The useBridgeCrud hook combines query and mutation operations for complete CRUD functionality:

typescript
import { useBridgeCrud } from '@pubflow/react';

function UserManagement() {
  const {
    data,
    isLoading,
    create,
    update,
    remove,
    refetch
  } = useBridgeCrud({ endpoint: 'users' });
  
  async function handleCreate(userData: any) {
    await create(userData);
    refetch();
  }
  
  async function handleUpdate(id: string, userData: any) {
    await update(id, userData);
    refetch();
  }
  
  async function handleDelete(id: string) {
    await remove(id);
    refetch();
  }
  
  return (
    <div>
      {/* Your UI here */}
    </div>
  );
}

Next Steps ​