Design+Code logo

Quick links

Suggested search

CodeSandbox Link

If you haven't, I highly encourage you to follow the first part of this tutorial. You can also access the complete code of this tutorial, with styling, at https://codesandbox.io/s/contentful-api-3lc0j.

Install the package

Before using the Contentful API, we'll need to install the SDK package . This package will allow us to easily fetch data from our Contentful space. In the Terminal, inside your project folder, run the following command.

npm install contentful

If the data you'll fetch with Contentful will be shared across the entire application, it would be best to create a context and have a global state. You can learn about the useContext and useReducer hooks in the useReducer with useContext tutorials ( part 1 , part 2 and part 3 ). In this tutorial, we'll just fetch the data in a custom hook called useContentful.

Get the space ID and preview token

To fetch data with the Content Delivery API, we need the space ID as well as a preview token. In Contentful, under the Settings tab, click on API keys under the Space Settings section. You should see your API keys there. If you don't have any API key, click on the Add API key button at the top right corner. If you already have an API key, under the Content delivery / preview tokens tab, click on the key.

Content delivery / preview tokens You'll see your Space ID. Below that, after the Content Delivery API access token, we'll see the Content Preview API access token. For the purposes of this tutorial, we'll use the Content preview API access token.

Contentful Part 2 image 2 When working in development mode, it's best to use the Content Preview API access token , as the data fetched will include the entries in Draft mode. When in production, it's best to use the Content Delivery API access token , so only the content that's published will be fetched.

Create the client

Create a new file called useContentful.js . Create the basic function layout, and don't forget to export it.

// useContentful.js

const useContentful = () => {

}

export default useContentful

Import the createClient function from Contentful at the top. That's what we'll use to connect to our Contentful account.

// useContentful.js

import { createClient } from "contentful"

The createClient function accepts an object containing a space ID and an access token. Inside of the function, create a Contentful client. Provide the space ID and the access token we got from Contentful. Since we're using the preview token, we need to provide the host as well. If you are using the delivery token, you can omit the host or change it to cdn.contentful.com.

// useContentful.js

const client = createClient({space: "", accessToken:"", host: "preview.contentful.com"})

For the purposes of this tutorial, we'll hard-code the space and accessToken. Remember to never hard-code your keys when committing to Github or pushing your work to production, as it's a big security flaw.

Fetch all authors

Now, we'll use the client variable we just created and call the getEntries function to fetch all authors. But first, let's create a function called getAuthors inside of the useContentful hook. Since the getEntries function returns a promise, we need to mark the getAuthors function as asynchronous.

// useContentful.js

const getAuthors = async () => {
    
}

Inside of getAuthors , let's get the author entries. The getEntries function accepts an object, which is optional. If you don't pass any argument to the function, it'll fetch everything from your Contentful space. We'll specify that we want to get all the author entries, and just fetch the fields (and not all the system information related to each entry).

// useContentful.js

const getAuthors = async () => {
  try {
    const entries = await client.getEntries({
      content_type: "author",
      select: "fields"
    });
    return entries
  } catch (error) {
    console.log(`Error fetching authors ${error}`);
  }
};

Remember to wrap everything in a try catch statement, to catch any error that might be thrown, and to await the getEntries function. For now, we'll only console log the entries. If you wish to order the entries by a specific field, for example by the author name, you can add the following line to the object you passed to the getEntries function.

order: "fields.name",

If you have another content type, for example courses, and you wish to select only the courses with React as a subject, you'll add the following line to the object you passed to the getEntries function.

"fields.subject": "React",

Before the closing bracket of the useContentful hook, we'll return an object containing the getAuthors function.

// useContentful.js

return { getAuthors }

Sanitize the data

Now, it's time to sanitize the data! Sanitizing the data means only taking the fields that we really need, instead of taking the whole object, with key-value pairs that we don't need. Let's import the useContentful hook in our App.js file.

// App.js

import useContentful from "./useContentful"

We'll get the getAuthors function from the useContentful hook.

// App.js

const { getAuthors } = useContentful()

Let's import the useEffect and useState hooks at the top.

// App.js

import { useEffect, useState } from "react"

Let's define both of the hooks. We'll define a state called authors , where we'll save the authors we fetched from Contentful.

// App.js

const [authors, setAuthors] = useState([])

Let's just print the response in the console in the useEffect.

// App.js

useEffect(() => {
	getAuthors().then((response) => console.log(response));
})

You'll see that we can a big object, with a lot of layers and some useless data.

Contentful Part 2 image 3 Let's go back to useContentful and sanitize that object, to only return an array of authors. We'll discard any key-value pairs in the entries object that we don't need.

// useContentful.js

const getAuthors = async () => {
  try {
    const entries = await client.getEntries({
      content_type: "author",
      select: "fields"
    });

    const sanitizedEntries = entries.items.map((item) => {
      const avatar = item.fields.avatar.fields;
      return {
        ...item.fields,
        avatar
      };
    });

    return sanitizedEntries;
  } catch (error) {
    console.log(`Error fetching authors ${error}`);
  }
};

In the function above, we're mapping through the entries items . For each item, we're taking only the fields of the avatar object, and returning that avatar variable, along with the fields of the item only. Finally, we're returning the sanitizedEntries. Back in App.js , we'll set the authors state with the response of the getAuthors function.

// App.js

useEffect(() => {
  getAuthors().then((response) => setAuthors(response));
});

Displaying the data

Finally, now that we have the data, we can just display it! Let's first create an author card. You can take the one below, or code your own!

// AuthorCard.js

import styled from "styled-components";

const AuthorCard = ({ author }) => {
  return (
    <Wrapper background={author.avatar.file.url}>
      <TextContainer>
        <Title>{author.name}</Title>
        <Subtitle>{author.description}</Subtitle>
      </TextContainer>
    </Wrapper>
  );
};

export default AuthorCard;

const Wrapper = styled.div`
  display: grid;
  align-items: flex-end;
  width: 240px;
  height: 240px;
  border-radius: 20px;
  box-shadow: 0px 20px 40px rgba(52, 53, 99, 0.2),
    0px 1px 3px rgba(0, 0, 0, 0.05);
  background: ${(props) =>
    props.background && `url(${props.background}) center no-repeat`};
  background-size: auto 150%;
`;

const TextContainer = styled.div`
  cursor: pointer;
  display: grid;
  background: rgba(255, 255, 255, 0.3);
  padding: 20px;
  gap: 10px;
  width: 100%;

  :hover {
    height: fit-content;
    width: auto;

    p:last-child {
      visibility: visible;
      display: block;
    }
  }
`;

const Title = styled.p`
  font-style: normal;
  font-weight: 500;
  font-size: 20px;
  margin: 0;
  font-weight: bold;
  color: #000000;
  margin: 0px;
`;

const Subtitle = styled.p`
  font-weight: normal;
  font-size: 12px;
  font-style: italic;
  color: rgba(0, 0, 0, 0.7);
  margin: 0px;
  visibility: hidden;
  display: none;
`;

Now, in App.js , we'll just need to map through the authors array and, for each author, display the AuthorCard . Don't forget to import the AuthorCard at the top of the file.

// App.js

import AuthorCard from "./AuthorCard";

{authors.map((author, index) => (
	<AuthorCard key={index} author={author} />
))}

Learn with videos and source files. Available to Pro subscribers only.

Purchase includes access to 50+ courses, 320+ premium tutorials, 300+ hours of videos, source files and certificates.

BACK TO

Contentful Part 1

READ NEXT

Gatsby and Shopify Part 1

Templates and source code

Download source files

Download the videos and assets to refer and learn offline without interuption.

check

Design template

check

Source code for all sections

check

Video files, ePub and subtitles

Browse all downloads