How to Build SPAs With Redux Thunk for API Handling

How to Build SPAs With Redux Thunk for API Handling

Building Single Page Applications (SPAs) using Redux Thunk for API handling is a powerful way to manage state and asynchronous actions in your application. SPAs are known for their high performance and dynamic user experiences. In this article, we will explore how to set up a SPA with Redux Thunk to handle API requests efficiently.

Understanding Redux Thunk

Redux Thunk is a middleware that allows you to write action creators that return a function instead of an action. This function can then perform asynchronous dispatches, making it perfect for handling API calls in SPAs.

Setting Up Your Project

Start by creating a new React project using Create React App:

npx create-react-app my-spa

Next, navigate to your project directory:

cd my-spa

Then, install Redux, React-Redux, and Redux Thunk:

npm install redux react-redux redux-thunk

Creating Your Redux Store

In your `src` directory, create a folder named `store` and under it, create a file called `store.js`. Inside `store.js`, configure your Redux store:

import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducers';
const store = createStore(rootReducer, applyMiddleware(thunk));
export default store;

Setting Up Reducers

In the `store` directory, create a folder named `reducers`. Within that folder, create a file named `index.js` and another named `apiReducer.js`. The `apiReducer.js` will handle your API state:

const initialState = {
    data: [],
    loading: false,
    error: null,
};
const apiReducer = (state = initialState, action) => {
    switch (action.type) {
        case 'FETCH_DATA_REQUEST':
            return { ...state, loading: true, error: null };
        case 'FETCH_DATA_SUCCESS':
            return { ...state, loading: false, data: action.payload };
        case 'FETCH_DATA_FAILURE':
            return { ...state, loading: false, error: action.payload };
        default:
            return state;
    }
};
export default apiReducer;

Update `index.js` to combine your reducers:

import { combineReducers } from 'redux';
import apiReducer from './apiReducer';
const rootReducer = combineReducers({
    api: apiReducer,
});
export default rootReducer;

Creating Action Creators

Create another folder in `store` called `actions`, and inside it create a file named `apiActions.js`. This will contain action creators for your API calls:

import axios from 'axios';
export const fetchDataRequest = () => ({
    type: 'FETCH_DATA_REQUEST',
});
export const fetchDataSuccess = (data) => ({
    type: 'FETCH_DATA_SUCCESS',
    payload: data,
});
export const fetchDataFailure = (error) => ({
    type: 'FETCH_DATA_FAILURE',
    payload: error,
});
export const fetchData = () => {
    return (dispatch) => {
        dispatch(fetchDataRequest());
        axios.get('https://api.example.com/data')
            .then((response) => {
                const data = response.data;
                dispatch(fetchDataSuccess(data));
            })
            .catch((error) => {
                const errorMsg = error.message;
                dispatch(fetchDataFailure(errorMsg));
            });
    };
};

Connecting Redux to Your Component

Now, let's connect your Redux store to a React component. Create a component called `DataComponent.js` in the `src` folder:

import React, { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { fetchData } from './store/actions/apiActions';
const DataComponent = () => {
    const dispatch = useDispatch();
    const { data, loading, error } = useSelector((state) => state.api);
useEffect(() => {
        dispatch(fetchData());
    }, [dispatch]);
if (loading) return 

Loading...

; if (error) return

Error: {error}

; return (

Data Fetched from API

    {data.map((item) => (