Examples
Short, copy-paste recipes for things most apps need. Each one works with the default export or your own instance.
On this page
#Fetch and render a list
JavaScript
const list = document.querySelector('#products');
const products = await relay.get('/api/products', { searchParams: { inStock: true } }).json();
list.innerHTML = products
.map((p) => `<li>${p.name} <span>$${p.price.toFixed(2)}</span></li>`)
.join('');#Submit a form
JavaScript
form.addEventListener('submit', async (event) => {
event.preventDefault();
const data = Object.fromEntries(new FormData(form));
try {
await relay.post('/api/contact', { json: data });
form.replaceWith('Thanks! We\'ll be in touch.');
} catch (error) {
status.textContent = error.status === 422 ? 'Please check the highlighted fields.' : 'Something went wrong.';
}
});#Refresh an expired token
Refresh the session once when the API returns 401, then replay the original request.
auth.js
let refreshing = null;
api.interceptors.response.use(async (response, request) => {
if (response.status !== 401 || request.retried) return response;
refreshing ??= relay.post('/auth/refresh').json().finally(() => (refreshing = null));
const { token } = await refreshing;
session.token = token;
return api.retry(request);
});#Upload a file
JavaScript
const body = new FormData();
body.append('file', input.files[0]);
body.append('folder', 'invoices');
const { url } = await relay.post('/api/uploads', { body, timeout: 60_000 }).json();#Poll until a job finishes
JavaScript
async function waitForExport(id) {
for (let attempt = 0; attempt < 20; attempt++) {
const job = await api.get(`exports/${id}`).json();
if (job.status === 'done') return job.downloadUrl;
if (job.status === 'failed') throw new Error(job.reason);
await new Promise((r) => setTimeout(r, Math.min(1000 * 2 ** attempt, 15_000)));
}
throw new Error('Export timed out');
}#Run requests in parallel
JavaScript
const [user, orders, invoices] = await Promise.all([
api.get('me').json(),
api.get('orders', { searchParams: { limit: 5 } }).json(),
api.get('invoices', { searchParams: { status: 'open' } }).json(),
]);#Use it in a React hook
useApi.js
import { useEffect, useState } from 'react';
export function useApi(path) {
const [state, setState] = useState({ data: null, error: null, loading: true });
useEffect(() => {
const controller = new AbortController();
api.get(path, { signal: controller.signal }).json()
.then((data) => setState({ data, error: null, loading: false }))
.catch((error) => error.code !== 'ABORTED' && setState({ data: null, error, loading: false }));
return () => controller.abort();
}, [path]);
return state;
}Was this page helpful?
Last updated