Fetching data from APIs

Version: 1.0.0

Fetching data is a common requirement when building websites or applications. deco.cx provides a data-fetching solution that loads data on the server-side and is flexible enough to allow business users to customize how data is fetched, just how they can configure Section's props.

In this tutorial you'll learn how to fetch data from an external API and feed that into a Section using Loaders.

What we'll build

The example use-case we'll follow is simple, but it has a lot of complexities we have on data fetching:

  • Fetch dog facts data from the Dog API allowing the user to configure how many facts are being fetched on deco.cx's Admin.
  • Render those facts in a Section.
Section rendering data fetched from API

Preview of DogFacts Section showing data returned from API

Data returned from the Dog Facts API

Data returned from the Dog Facts API being called elsewhere

1. Creating the Section

First, let's create a Section that will render the data fetched from the API. Create the DogFacts.tsx section in the sections/ folder of your project.

If we make an HTTP request to the Dog Fact API, we will see that it returns a JSON in the following format:

Open in your browser this URL with params for the Dog Fact API

{
  "facts": [
    "The Labrador is so popular, in 2006 there were approximately 
    3-5 times more Labs as there were German Shepherds or Golden Retrievers."
  ],
  "success": true
}

Note that the only thing we care about is the "facts" property. Therefore, we will create a section that is prepared to receive these facts and render them in any way we want.

To do this, we will create a type called DogFact that contains only one property called fact, which is the string represented by the message.

Let's see this in action by creating a new section:

Paste the following code:

export interface DogFact {
  fact: string;
}

export interface Props {
  title: string;
  dogFacts: string[];
}

export default function DogFacts({ title, dogFacts }: Props) {
  return (
    <div class="p-4">
      <h1 class="font-bold">{title}</h1>
      <ul>
        {dogFacts.map((fact) => <li>{fact}</li>)}
      </ul>
    </div>
  );
}

At this point, you can check in the admin (in your local environment) that this component can already be used with static data, which doesn't make much sense for our use case.

2. Creating the Loader and testing the Section

Now let's create a Loader that will fetch the data from the Dog Fact API and pass it to the Section.

Loaders allow you to define how data is fetched and transformed before it is passed on to a Section. They are regular Typescript functions that can use async functions like fetch. Loaders can be "plugged" into a Section via one of the Section's props, and that happens based on the return type of the Loader (the return type of the Loader is the input type of the Section).

  1. Define what will be the input Props of your loader.
  2. Export a function called loader in the same file as your Section.
import type { SectionProps } from "deco/mod.ts";

// Props type that will be configured in deco.cx's Admin
export interface Props {
  title: string;
  numberOfFacts?: number;
}

export async function loader(
  { numberOfFacts, title }: Props,
  _req: Request,
) {
  const { facts: dogFacts } = (await fetch(
    `https://dogapi.dog/api/facts?number=${numberOfFacts ?? 1}`,
  ).then((r) => r.json())) as { facts: string[] };
  return { dogFacts, title };
}

export default function DogFacts(
  { title, dogFacts }: SectionProps<typeof loader>,
) {
  return (
    <div class="p-4">
      <h1 class="font-bold">{title}</h1>
      <ul>
        {dogFacts.map((fact) => <li>{fact}</li>)}
      </ul>
    </div>
  );
}

Note: The SectionProps type is a helper type that is used to infer the return type of the loader.

3. Testing the Section

  1. Run the server locally with DECO_ENV_NAME={environment_name} deno task start.
  2. Go to https://deco.cx/admin in your site and make sure that your environment is selected in the Environment Selector in the upper right corner of the Admin.
  3. Go to Sections and search for DogFacts in the left sidebar.
  4. Configure the props of the selected Loader (numberOfFacts) with a desired number (e.g., 4).

Now, let's see it working hooking it up with a Section.

DogFacts Section rendering data fetched from the API

That's it! Now you've built a Section that displays data fetched from an external API using a Loader, making it all configurable by business users as desired. We recommend exporting filters and sort options in Loader's props to make it more reusable in deco.cx's Admin.

Further reading

Loaders are powerful components for handling dynamic data and solve most of the requirements when dealing with data coming from APIs. The deco.cx platform solves a myriad of other use cases related to dynamic data that we can use, check the following links to understand how to use them.

Was this page helpful?
Can't find what you're looking for? Spot an error in the documentation? Get in touch with us on our Community Forum
Continue reading