0
0
RemixHow-ToBeginner ยท 4 min read

How to Load Data from Database in Remix Framework

In Remix, load data from a database by creating an async loader function that fetches data on the server before rendering. Use useLoaderData() in your component to access this data safely and efficiently.
๐Ÿ“

Syntax

The main parts to load data from a database in Remix are:

  • loader: An async function exported from your route file that fetches data from the database.
  • useLoaderData(): A React hook to access the data returned by the loader inside your component.

The loader runs on the server before rendering, so you can safely query your database there.

typescript
import { json } from '@remix-run/node';
import { useLoaderData } from '@remix-run/react';

export async function loader() {
  const data = await fetchDataFromDatabase();
  return json(data);
}

export default function Component() {
  const data = useLoaderData();
  return <div>{JSON.stringify(data)}</div>;
}
๐Ÿ’ป

Example

This example shows how to load a list of users from a database using a loader and display them in a Remix route component.

typescript
import { json } from '@remix-run/node';
import { useLoaderData } from '@remix-run/react';

// Simulated database query function
async function getUsers() {
  return [
    { id: 1, name: 'Alice' },
    { id: 2, name: 'Bob' },
    { id: 3, name: 'Charlie' }
  ];
}

export async function loader() {
  const users = await getUsers();
  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>Alice</li> <li>Bob</li> <li>Charlie</li> </ul> </main>
โš ๏ธ

Common Pitfalls

  • Trying to fetch data directly inside the component instead of using a loader causes data to load on the client, losing Remix's server-side benefits.
  • Not returning data wrapped in json() from the loader can cause errors or unexpected results.
  • Forgetting to use await when calling async database functions inside the loader leads to unresolved promises.
  • Accessing database code directly in components breaks Remix's data loading pattern and can expose secrets to the client.
typescript
/* Wrong way: fetching data inside component (runs on client) */
import { useEffect, useState } from 'react';

export default function Users() {
  const [users, setUsers] = useState([]);
  useEffect(() => {
    fetch('/api/users')
      .then(res => res.json())
      .then(data => setUsers(data));
  }, []);
  return <div>{JSON.stringify(users)}</div>;
}

/* Right way: use loader for server-side data fetching */
import { json } from '@remix-run/node';
import { useLoaderData } from '@remix-run/react';

async function getUsersFromDatabase() {
  // Implement your database fetching logic here
  return [
    { id: 1, name: 'Alice' },
    { id: 2, name: 'Bob' },
    { id: 3, name: 'Charlie' }
  ];
}

export async function loader() {
  const users = await getUsersFromDatabase();
  return json(users);
}

export default function Users() {
  const users = useLoaderData();
  return <div>{JSON.stringify(users)}</div>;
}
๐Ÿ“Š

Quick Reference

  • loader: async function to fetch data on server
  • json(): wraps data for Remix response
  • useLoaderData(): hook to access loader data in component
  • Always keep database calls inside loader for security and performance
โœ…

Key Takeaways

Use an async loader function to fetch database data on the server in Remix.
Return data wrapped in json() from the loader for proper response formatting.
Access loader data in your component with useLoaderData() hook.
Avoid fetching data directly inside components to keep server-side benefits.
Keep database logic inside loaders to protect secrets and improve performance.