Integrating a React Application with a Backend API Using Redux Toolkit

A easy to folow template for integration

Integrating a React application with a backend API is a common requirement in web development. In this guide, we will walk through the process of setting up such an integration using Redux Toolkit and custom hooks in a React application. By the end, you’ll have a template you can follow to easily fetch and manage data from your backend server.

Setting Up Your Project

  • Create a React App: Use Create React App to set up your project.

    npx create-react-app my-app
    cd my-app
    
  • Install Redux Toolkit and React-Redux:

    npm install @reduxjs/toolkit react-redux
    

Project Structure

Organize your project for scalability. A typical structure might look like this:

src/
|-- components/
|   |-- Banner.js
|-- hooks/
|   |-- useTopBannerFetch.js
|-- redux/
    |-- store.js
    |-- topBannerSlice.js
|-- services/
    |--api
        |- fetchBanners.js
|-- App.js
|-- .env
|-- index.js

Step 1: Setting Up Axios and Async Thunks

First, we need to set up an asynchronous function to fetch data from our backend API using Axios and Redux Toolkit’s createAsyncThunk.

//fetchBanners.js

import { createAsyncThunk } from "@reduxjs/toolkit";
import axios from "axios";

const fetchBannerMiddleware = createAsyncThunk('fetchTopBanners', async () => {
    const response = await axios.get(process.env.REACT_APP_BANNER_URI);
    return response.data;
});

export default fetchBannerMiddleware;

Here, fetchBannerMiddleware is an asynchronous thunk that fetches banner data from the backend API defined by the environment variable REACT_APP_BANNER_URI.

Step 2: Defining Environment Variables

Define your backend URLs in a .env file at the root of your project. This helps manage URLs easily across different environments (development, production, etc.). Keep in mind that in order to load these data property names should start with ‘REACT_APP_’

REACT_APP_BACKEND_URI=http://localhost:8080
REACT_APP_BANNER_URI=http://localhost:8080/banner

Step 3: Creating a Redux Slice

Next, create a Redux slice to manage the state of the fetched data. This slice will handle the different states of the fetch request (pending, fulfilled, and rejected).

// topBannerSlice.js

import { createSlice } from "@reduxjs/toolkit";
import fetchBannerMiddleware from "../services/api/fetchBanners";

export const topBannerSlice = createSlice({
  name: "topBanner",
  initialState: {
    topBanner: false,
    banners: [],
    status: 'init',
    errorData: null
  },
  reducers: {},
  extraReducers: (builder) => {
    builder
      .addCase(fetchBannerMiddleware.fulfilled, (state, action) => {
        state.banners = action.payload;
        state.status = 'success';
      })
      .addCase(fetchBannerMiddleware.rejected, (state, action) => {
        state.errorData = action.payload;
        state.status = 'error';
      })
      .addCase(fetchBannerMiddleware.pending, (state) => {
        state.status = 'pending';
      });
  },
});

export default topBannerSlice.reducer;

Step 4: Configuring the Store

Configure the Redux store to include the new slice. This ensures that the state managed by the slice is part of the global state.


// store.js

import { configureStore } from "@reduxjs/toolkit";
import topBannerReducer from "../slices/topBannerSlice"; // Adjust the import path as necessary


export const store = configureStore({
  reducer: { bannerReducer: persistedReducer },
});

Step 5: Creating a Custom Hook

Create a custom hook to fetch the banner data and return the state values. This hook will be used in your components to access the data.

// useTopBannerFetch.js

import { useDispatch, useSelector } from "react-redux";
import fetchBannerMiddleware from "../services/api/fetchBanners";
import { useEffect } from "react";

const useTopBannerFetch = () => {
    const dispatch = useDispatch();
    const bannerData = useSelector((state) => state.bannerReducer.banners);
    const status = useSelector((state) => state.bannerReducer.status);
    const error = useSelector((state) => state.bannerReducer.errorData);

    useEffect(() => {
        dispatch(fetchBannerMiddleware());
    }, [dispatch]);

    return { bannerData, status, error };
};

export default useTopBannerFetch;

Step 6: Using the Custom Hook in a Component

Finally, use the custom hook in your component to fetch and display the banner data.

// Banner.js

import React, { useState } from "react";
import { Link } from "react-router-dom";
import Slider from "react-slick"; // Assuming you're using react-slick for the slider
import Image from "../designLayouts/Image";
import useTopBannerFetch from "../../hooks/useTopBannerFetch";

const Banner = () => {
  const [dotActive, setDocActive] = useState(0);
  const { bannerData, status, errorData } = useTopBannerFetch();

  if (status === 'pending') return <div>Loading...</div>;
  if (status === 'error') return <div>Error: {errorData}</div>;
  // other codes 
  return (
    <Slider {...settings}>
      {bannerData && bannerData.map((banner) => (
        <Link to="/offer" key={banner.id}>
          <div>
            <Image imgSrc={banner.imgSrc} />
          </div>
        </Link>
      ))}
    </Slider>
  );
};

export default Banner;

Conclusion

By following these steps, you can effectively integrate a React application with a backend API using Redux Toolkit. This approach ensures a clean and manageable way to handle asynchronous data fetching and state management. Use this template as a foundation and adjust it according to your project requirements. Happy coding!


BawaDev

真诚赞赏,手留余香

使用微信扫描二维码完成支付