How to Load Data from API in Remix: Simple Guide
In Remix, you load data from an API by using the
loader function to fetch data on the server side before rendering. The useLoaderData hook then accesses this data inside your component for display.Syntax
The loader function runs on the server and fetches data before the page renders. Inside it, you use fetch to call your API and return the data as JSON. The useLoaderData hook inside your component accesses this data.
export async function loader(): fetches datareturn json(data): sends data to the componentconst data = useLoaderData(): gets data in the component
tsx
import { json } from "@remix-run/node"; import { useLoaderData } from "@remix-run/react"; export async function loader() { const response = await fetch("https://api.example.com/data"); const data = await response.json(); return json(data); } export default function MyComponent() { const data = useLoaderData(); return ( <div> <h1>Data from API</h1> <pre>{JSON.stringify(data, null, 2)}</pre> </div> ); }
Example
This example shows how to load a list of users from a public API and display their names on the page. The loader fetches the data, and useLoaderData renders it.
tsx
import { json } from "@remix-run/node"; import { useLoaderData } from "@remix-run/react"; export async function loader() { const response = await fetch("https://jsonplaceholder.typicode.com/users"); const users = await response.json(); return json(users); } export default function Users() { const users = useLoaderData(); return ( <main> <h1>User List</h1> <ul> {users.map(user => ( <li key={user.id}>{user.name}</li> ))} </ul> </main> ); }
Output
<main>
<h1>User List</h1>
<ul>
<li>Leanne Graham</li>
<li>Ervin Howell</li>
<li>Clementine Bauch</li>
<li>Patricia Lebsack</li>
<li>Chelsey Dietrich</li>
<li>Mrs. Dennis Schulist</li>
<li>Kurtis Weissnat</li>
<li>Nicholas Runolfsdottir V</li>
<li>Glenna Reichert</li>
<li>Clementina DuBuque</li>
</ul>
</main>
Common Pitfalls
1. Forgetting to return JSON: The loader must return data wrapped with json() from @remix-run/node to work properly.
2. Using fetch on the client inside loader: The loader runs on the server, so use server-safe fetch or polyfill if needed.
3. Not handling errors: Always check the API response status and handle errors to avoid crashes.
tsx
/* Wrong way: returning raw data without json() */ export async function loader() { const response = await fetch("https://api.example.com/data"); const data = await response.json(); return data; // โ Should use json(data) } /* Right way: */ import { json } from "@remix-run/node"; export async function loader() { const response = await fetch("https://api.example.com/data"); if (!response.ok) { throw new Response("Failed to load", { status: response.status }); } const data = await response.json(); return json(data); // โ Correct }
Quick Reference
- loader(): Server function to fetch data before render.
- json(data): Wraps data for Remix response.
- useLoaderData(): Hook to access loader data in component.
- Handle errors: Check response status and throw if needed.
- Server-side fetch: Runs on server, no client-side fetch in loader.
Key Takeaways
Use the loader function to fetch API data on the server before rendering.
Wrap returned data with json() to send it properly to your component.
Access the loaded data inside your component with useLoaderData().
Always check API response status and handle errors in the loader.
Remember loader runs server-side, so use server-safe fetch methods.