Fetching data using “loader()”

We want to load our data from an external resource, and eventually that will be a database. We’ll start by cheating though, and continue to use our constant todoList. Start by creating a new function called loader outside Index.

export async function loader() {
  let tasks = [{
    id: 1,
    task: "Get started",
    deadline: 1,
  },
  {
    id: 2,
    task: "Do stuff",
    deadline: 2,
  },
  {
    id: 3,
    task: "Finish up",
    deadline: 3,
  }];
  return tasks ;
}

To use the data we return from this function, we need to use a Remix hook called useLoaderData(). At the top of your Index(), add this:

let todoList = useLoaderData();

For that to work, we need to import useLoaderDatafrom Remix. We’ll also import Form, because we’re going to need it in a minute:

import { Form, useLoaderData } from "remix";

If you run npm run dev in the terminal now, nothing should have changed in the browser. But now the data comes in through the loader() function and useLoaderData().

Let’s take it one step further, and actually use a database.

Install and use Prisma and SQLite

We need Prisma and Prisma Client. Install them with

npm install prisma @prisma/client

or, if you prefer yarn:

yarn add prisma @prisma/client

Then initialise prisma and set it up to use SQLite:

npx prisma init --datasource-provider sqlite

This creates a .envfile, and a folder called prisma in the root folder.

Update the file prisma/schema.prisma with a model:

generator client {
  provider = "prisma-client-js"
}

datasource db {
    provider = "sqlite"
    url      = env("DATABASE_URL")
}

model tasks {
    id       Int    @id @default(autoincrement())
    task     String
    deadline String
}

Now it’s time to create the database, and we’ll let Prisma do it for us:

npx prisma migrate dev --name initialize

This creates a file prisma/dev.db and a folder prisma/migrations. Inside is a file named after the current date and time, followed by _initialize. The last bit comes from the name parameter in the command above.

Now we have a database, let’s use it in our page.

Create a new folder app/utilities and create a file called db.server.ts inside it.

Add this to db.server.ts:

import { PrismaClient } from "@prisma/client";

let db = new PrismaClient();
export { db };

Now create a second file in utilities and name it db.ts. Add this content to it:

import { db } from "./db.server";

export async function getTasks() {
    let tasks = await db.tasks.findMany();
    db.$disconnect();
    return tasks;
}

Now we have everything we need to fetch data from the database instead of hard coding it in our file. Let’s change the loader() in index.tsx:

import { getTasks } from "~/utilities/db";

export async function loader() {
  let tasks = await getTasks();
  return tasks ;
}

If you run npm run dev, you should see that we no longer have any tasks on the page. That is actually good, because it means everything is working and the database is empty. Had there been a problem, we would’ve seen an error message.

You can try using a tool like “DB Browser for SQLite” and add a few tasks if you like. We’ll add the code to do it in our app in the next part of this series.

About the author

For the last three decades, I've worked with a variety of technologies. I'm currently focused on fullstack development. On my day to day job, I'm a senior teacher and course developer at a higher vocational school in Malmoe, Sweden. I'm also an occasional tech speaker and a mentor. Do you want to know more? Visit my website!