Redux tutorial with Contentful
![How to use Redux to manage application state and data-fetching logic in a React project, and how to apply these techniques to data coming from Contentful.](https://images.ctfassets.net/fo9twyrwpveg/3WGgGii9rxXxeVG9cOGsOb/0f03554c148cb3a2bb028766e7aaf443/2023-03_getting_started_with_redux.jpg?fm=jpg&q=90&w=1536)
Redux is a state management library for JavaScript. It brought the concept of unidirectional data flow to the world of frontend development, and is used by a variety of mainstream apps. The library is written in plain JavaScript so it works with any framework, whether that’s Vue, Angular, Svelte, or no framework at all.
This tutorial will guide you through using Redux to manage application state and data-fetching logic in a React project and how to apply these techniques to data coming from Contentful. All the code in this tutorial can be found in this repository.
Prerequisites
To follow along, you’ll need:
A Contentful account. Sign up if you do not have one.
Intermediate knowledge of JavaScript and familiarity with Redux.
Node.js version 18 or above.
Prepare your Contentful space: Creating a content model
Using your browser, navigate to your Contentful dashboard. Create a space, then create a content model to store your data. We’ll be building an example auction application.
This tutorial uses woodcraft_auction
as the name of the content type. Feel free to use another name.
![Using your browser, navigate to your Contentful dashboard. Create a space, then create a content model to store your data. We’ll be building an example auction application.](https://images.ctfassets.net/fo9twyrwpveg/If57c8DIQS57DhS9kKacs/b6164d6fda1b349ba0f05e0e1e7df636/ink__2_.png)
Note: If you’re unfamiliar with Contentful, refer to our beginner’s guide.
Add the following fields to the woodcraft_auction
content type:
A short text field called name for storing the name of each item available to be auctioned.
A rich text field called
description
for describing the available item.A date & time field called
date_posted
to specify an item’s posting date.A media field for storing several images of the item. Ensure you select many files as the type of media field.
A number field type called
price
to specify the item’s costs.
Now, you have five fields within your content type.
![Now, you have five fields within your content type.](https://images.ctfassets.net/fo9twyrwpveg/5s1b4oirqRb0zmOJDS6Yzk/3cecef5fe17d4cd437c1121a741601ec/ink__3_.png)
Click the Save button at the top. This saves the fields you’ve added to the content type.
Adding a sample content entry
Add a sample entry into the woodcraft_auction
content type you created. This entry is the first data that the React application will fetch with Redux.
To add your first entry, switch to the Content Editor page of the Contentful dashboard. Next, click the Add Entry button and provide content for the name, description
, date_posted
, images
, and price
fields. Ensure you publish your content by clicking the Publish button.
![Add a sample entry into the woodcraft_auction content type you created. This entry is the first data that the React application will fetch with Redux.](https://images.ctfassets.net/fo9twyrwpveg/429jKCxRPoxPGFktyB39M6/4f2a85225447a1c12a1cf7b62c46922f/ink__4_.png)
Creating a Contentful Content Delivery API token
Next, you need to get an API key. The Contentful Content Delivery API (CDA) is a read-only API that allows you to fetch content you’ve stored within a Contentful space. Full instructions to create your own can be found here.
Building the Redux application
You’re now ready to build your Redux application. You’ll start by creating a standalone React app following the steps below.
Creating a React application
First, generate a React project called react-contentful-redux
using the React template for Vite via the command-line interface.
npm create vite@latest react-contentful-redux -- --template react
Next, execute the two commands below.
cd react-contentful-redux
npm install @contentful/rich-text-react-renderer @reduxjs/toolkit react-redux
This navigates into the react-contentful-redux
project and installs the dependencies necessary to build the project.
Finally, create a file called .env
within the react-contentful-redux
project directory. Use the file to store your Contentful credentials securely in the following format. Ensure you replace the placeholder values with their corresponding values from Contentful.
Now you can use the stored credentials in a client class to fetch data from Contentful.
⚠️ Because this is a client-side application, your environment variables will be sent to the user’s browser. As a result, Vite requires us to add the VITE_ prefix to make us aware of this.
Creating a Contentful client
Create a ContentfulApiClient.js
file within the React application’s src
directory. The file contains all the logic for interacting with the Content Delivery API. We use a ContentfulClient class to keep the code clean and avoid duplicated API requests.
Add the following code into the empty ContentfulApiClient.js
file:
Adding Redux to the application
The Redux documentation recommends the Redux Toolkit (RTK) as the “official, opinionated, batteries-included toolset.” RTK includes many tools to work with Redux, like “thunks” for asynchronous operations, and many others.
Start by creating a directory called state
within the src
directory. This stores all additional files you’ll make while building the slice and action for the application.
Creating a Redux action
Create a product.action.js
file within the state
directory to store the actions for the application.
Add this code block below to the actions in the product.action.js
file. This creates an instance of the ContentfulClient
class and creates a thunk:
The callback
method of the fetchArtworks
thunk above invokes the getItems
method. This fetches all the published entries within the project’s content type on Contentful. Furthermore, the createAsyncThunk
method allows you to track the state of the network requests with minimal effort.
Next, create an RTK slice to place the data resolved from the fetchArtworks thunk into the Redux state.
Creating a Redux slice
Create a product.slice.js
file within the state directory. Add the content of the next code block to the file.
The slice above has an empty array of artworks as its initial state. After resolving the promise from the fetchArtworks
thunk, the code sets the `artwork` property of the current state to the returned value.
Creating a Redux store
After creating the reducer functions, we create the Redux store with `configureStore`. Then, we wrap the entire React application with the Provider from the react-redux package to give the children components access to the store.
Create a store.js
file in the state directory. Build the Redux store
by adding the following:
We make sure that devTools
is only active when in development by passing an option to the configureStore()
method.
Next, open the App.jsx
file and replace the default boilerplate code with this:
The Redux part of the application is now set up and ready to use with the React components.
Building the application components
The React application only uses two components: one for the banner section and the other to render a card.
To create the styles to be used by the HTML Banner and Card components, replace the default boilerplate code in ./src/App.css
with the code below:
Open the index.css
file and delete the boilerplate style rules, as you no longer need them.
In the next section, you will create a components
directory within the existing src
directory. This directory will store the files for the Banner and Card components.
Creating the Banner section
First, create a components
directory, then create a Banner.jsx
file inside it.
Next, add this code block to the file:
This displays the name and description of the service and a search field for customers to find available craftworks.
Creating the CraftCard
Now, create a Card.jsx
file within the components directory. Add the content of the following code block into the file.
The data displayed within the Card component above is passed in as props from the parent component that renders it. The @contentful/rich-text-react-renderer
package parses the Rich Text description.
The component uses the getAsset method from the ContentfulClient
class in a useEffect
hook. This fetches the entry data and stores the image URL in its local state immediately after the component renders and the image prop has a value.
Creating the Home page
In the src directory, create a Home directory containing an index.jsx file.
The index.jsx
file renders the Banner component, dispatches the fetchArtworks
thunk, and then displays the Contentful entries stored within the Redux state
using the Card
component.
Using the Redux application
To start the server and access it from your web browser, execute this command:
npm run dev
![Open the running react-contentful-redux application on http://localhost:5173/ in your web browser. View the default page that lists your Contentful entries.](https://images.ctfassets.net/fo9twyrwpveg/7dGRMEJyVi51vKewwp1LUQ/821f84fb6626bd58a4953449c5c1f331/ink__7_.png)
Open the running react-contentful-redux
application on http://localhost:5173/
in your web browser. View the default page that lists your Contentful entries.
![Your app made with Redux and Contentful.](https://images.ctfassets.net/fo9twyrwpveg/31SuLyUw1xgvfcYDM17ABj/8b756078b6a4585d482957c87c465a89/ink__8_.png)
Using the redux-devtools extension, you can view, monitor, mutate, and debug Redux operations from your browser.
The image below shows the fetchArtworks
action pending and then resolved alongside the state of the products
reducer.
![The image below shows the fetchArtworks action pending and then resolved alongside the state of the products reducer.](https://images.ctfassets.net/fo9twyrwpveg/4OZiyuO4jD2s6rpUJCLLaT/f6e0a79a2d501aeaaa0861519c5b17ac/ink__9_.png)
Wrapping up
Congratulations on completing this hands-on guide! As demonstrated, Redux provides a better way to distribute the data returned from Contentful without excessive props drilling.
As you build your next React application to display your digital content stored within Contentful, consider using Redux to better manage the state of your application and its data-fetching logic.