How to Fetch Data in Remix: Simple Guide with Examples
In Remix, you fetch data by exporting a
loader function that runs on the server before rendering. Inside the loader, you can fetch data asynchronously and return it as JSON. Then use useLoaderData() in your component to access the fetched data.Syntax
Remix uses a special loader function to fetch data on the server side before rendering the component. The loader returns data that the component can access using useLoaderData().
export async function loader(): Runs on the server to fetch data.return json(data): Sends data as JSON to the component.const data = useLoaderData(): Hook to get the loader data inside the component.
javascript
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 Loaded</h1> <pre>{JSON.stringify(data, null, 2)}</pre> </div> ); }
Output
<div>
<h1>Data Loaded</h1>
<pre>{...fetched JSON data...}</pre>
</div>
Example
This example fetches a list of users from a public API in the loader and displays their names in a list. It shows how Remix handles server-side data fetching and passes it to the component.
javascript
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 in json() from @remix-run/node to work properly.
2. Using client-side fetch inside the loader: Always use fetch inside the loader for server-side fetching, not inside the component.
3. Not using useLoaderData(): The component must call useLoaderData() to access the data returned by the loader.
javascript
/* Wrong: Fetching inside component (runs on client, no SSR) */ import React from "react"; export default function Wrong() { const [data, setData] = React.useState(null); React.useEffect(() => { fetch("https://api.example.com/data") .then(res => res.json()) .then(setData); }, []); if (!data) return <p>Loading...</p>; return <pre>{JSON.stringify(data, null, 2)}</pre>; } /* Right: Fetching inside loader (runs on server) */ import { json } from "@remix-run/node"; import { useLoaderData } from "@remix-run/react"; export async function loader() { const res = await fetch("https://api.example.com/data"); const data = await res.json(); return json(data); } export default function Right() { const data = useLoaderData(); return <pre>{JSON.stringify(data, null, 2)}</pre>; }
Quick Reference
- loader(): Async function to fetch data on the server.
- json(data): Wraps data to send JSON response.
- useLoaderData(): Hook to access loader data in component.
- Use server-side fetch in
loader, not client-side fetch in components. - Always return data from
loaderusingjson().
Key Takeaways
Use the async loader function to fetch data on the server before rendering.
Return data from loader wrapped in json() for Remix to handle it correctly.
Access loader data inside your component with useLoaderData() hook.
Avoid client-side fetch inside components for initial data loading.
Always handle errors and loading states appropriately in your UI.