Data Fetching ​
This guide covers data fetching patterns using Flowfull Client.
Basic Data Fetching ​
Simple GET Request ​
typescript
import { useState, useEffect } from 'react';
import { api } from '../lib/api';
function UserList() {
const [users, setUsers] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
async function fetchUsers() {
try {
const data = await api.get('/users');
setUsers(data);
} catch (err: any) {
setError(err.message);
} finally {
setLoading(false);
}
}
fetchUsers();
}, []);
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error}</div>;
return (
<ul>
{users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}Pagination ​
typescript
function PaginatedUserList() {
const [users, setUsers] = useState([]);
const [page, setPage] = useState(1);
const [totalPages, setTotalPages] = useState(1);
const [loading, setLoading] = useState(false);
useEffect(() => {
fetchUsers();
}, [page]);
async function fetchUsers() {
setLoading(true);
try {
const response = await api.query('/users')
.page(page)
.limit(10)
.execute();
setUsers(response.data);
setTotalPages(Math.ceil(response.meta.total / 10));
} catch (error) {
console.error('Error fetching users:', error);
} finally {
setLoading(false);
}
}
return (
<div>
{loading && <div>Loading...</div>}
<ul>
{users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
<div>
<button
onClick={() => setPage(p => Math.max(1, p - 1))}
disabled={page === 1 || loading}
>
Previous
</button>
<span>Page {page} of {totalPages}</span>
<button
onClick={() => setPage(p => Math.min(totalPages, p + 1))}
disabled={page === totalPages || loading}
>
Next
</button>
</div>
</div>
);
}Filtering and Sorting ​
typescript
function FilteredUserList() {
const [users, setUsers] = useState([]);
const [status, setStatus] = useState('all');
const [sortBy, setSortBy] = useState('name');
const [sortDir, setSortDir] = useState<'asc' | 'desc'>('asc');
useEffect(() => {
fetchUsers();
}, [status, sortBy, sortDir]);
async function fetchUsers() {
try {
let query = api.query('/users');
if (status !== 'all') {
query = query.filter('status', status);
}
query = query.orderBy(sortBy, sortDir);
const data = await query.execute();
setUsers(data);
} catch (error) {
console.error('Error fetching users:', error);
}
}
return (
<div>
<select value={status} onChange={(e) => setStatus(e.target.value)}>
<option value="all">All</option>
<option value="active">Active</option>
<option value="inactive">Inactive</option>
</select>
<select value={sortBy} onChange={(e) => setSortBy(e.target.value)}>
<option value="name">Name</option>
<option value="email">Email</option>
<option value="created_at">Created At</option>
</select>
<button onClick={() => setSortDir(d => d === 'asc' ? 'desc' : 'asc')}>
{sortDir === 'asc' ? '↑' : '↓'}
</button>
<ul>
{users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
</div>
);
}Search with Debouncing ​
typescript
import { useState, useEffect } from 'react';
import { api } from '../lib/api';
function SearchableUserList() {
const [query, setQuery] = useState('');
const [debouncedQuery, setDebouncedQuery] = useState('');
const [users, setUsers] = useState([]);
const [loading, setLoading] = useState(false);
// Debounce search query
useEffect(() => {
const timer = setTimeout(() => {
setDebouncedQuery(query);
}, 300);
return () => clearTimeout(timer);
}, [query]);
// Fetch users when debounced query changes
useEffect(() => {
if (debouncedQuery) {
searchUsers();
} else {
setUsers([]);
}
}, [debouncedQuery]);
async function searchUsers() {
setLoading(true);
try {
const data = await api.query('/users')
.filter('name', 'like', debouncedQuery)
.limit(10)
.execute();
setUsers(data);
} catch (error) {
console.error('Error searching users:', error);
} finally {
setLoading(false);
}
}
return (
<div>
<input
type="text"
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder="Search users..."
/>
{loading && <div>Searching...</div>}
<ul>
{users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
</div>
);
}Next Steps ​
- Making API Calls - Learn more about API calls
- Query Builder - Advanced query building
- Session Management - Understand session handling