Open In App

How to handle data fetching in React-Redux Applications ?

Last Updated : 01 Mar, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

Data fetching in React-Redux applications is a common requirement to retrieve data from APIs or other sources and use it within your components.

This article explores various approaches to handling data fetching in React-Redux applications, providing examples and explanations for each approach.

Approach 1: Using Thunk Middleware:

Thunk middleware allows you to write action creators that return a function instead of an action object. This function can perform asynchronous operations, such as fetching data, before dispatching actions.

Syntax to fetch data in Redux Application:

const fetchData = () => {
return async (dispatch) => {
dispatch(fetchDataRequest());
try {
const response = await api.getData();
dispatch(fetchDataSuccess(response.data));
} catch (error) {
dispatch(fetchDataFailure(error));
}
};
};

Approach 2: Using Redux Saga:

Redux Saga is a middleware library that helps manage side effects in Redux applications. It uses ES6 generators to make asynchronous code easier to read, write, and test.

Syntax to fetch data using Redux Saga:

function* fetchDataSaga() {
try {
const response = yield call(api.getData);
yield put(fetchDataSuccess(response.data));
} catch (error) {
yield put(fetchDataFailure(error));
}
}

Approach 3: Using Redux Toolkit with Async Thunks:

Redux Toolkit simplifies Redux usage by providing utilities for common Redux tasks, including handling asynchronous logic with async thinks.

React-Query:

React-Query is a library specifically designed for handling data fetching in React applications, offering a hook-based approach.

Syntax:

const { data, error, isLoading } = useQuery('data', api.getData);

Steps to handle data fetching in React-Redux:

Step 1: Create a new React project using Create React App. Open your terminal and run the following command:

npx create-react-app myapp

Step 2: Switching into App directory:

cd myapp

Step 3: Install Redux and React-Redux dependencies:

npm install redux react-redux redux-thunk @reduxjs/toolkit

Step 4: Choose Your Approach:

Depending on the chosen approach (Thunk Middleware, Redux Saga, or Redux Toolkit), install the necessary dependencies:

Thunk Middleware: npm install redux-thunk
Redux Saga: npm install redux-saga
Redux Toolkit: npm install @reduxjs/toolkit

Step 3: Configure Redux Store:

Set up your Redux store with the chosen approach and any additional middleware required.

Step 4: Write Data Fetching Logic:

Create action creators or sagas to handle data fetching operations.

Step 5: Integrate with Components:

Connect Redux store to your React components using the connect higher-order component or React-Redux hooks.

Project Structure:

folder

Folder Struture

The updated dependencies in package.json file will look like:

"dependencies": {
"redux": "^4.1.0",
"react-redux": "^7.2.4",
"redux-thunk": "^2.3.0", // If using Thunk Middleware
"redux-saga": "^1.1.3" // If using Redux Saga
}

Example: Below is the code example to show how to handle data fetching:

Javascript




import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { Provider } from 'react-redux';
import store from './store/configureStore';
 
ReactDOM.render(
    <Provider store={store}>
        <App />
    </Provider>,
    document.getElementById('root')
);


Javascript




import React from 'react';
import DataList from './components/DataList';
 
function App() {
  return (
    <div>
      <h1>Redux Data fetching Example</h1>
      <DataList />
    </div>
  );
}
 
export default App;


Javascript




//configureStore.js
import {
    configureStore
} from '@reduxjs/toolkit';
import dataReducer
    from '../reducers/dataReducer';
 
const store = configureStore({
    reducer: {
        data: dataReducer,
    },
});
 
export default store;


Javascript




//DataComponent.js
import React,
{
    useEffect
} from 'react';
import {
    useDispatch,
    useSelector
} from 'react-redux';
import { fetchData }
    from '../actions/dataActions';
 
const DataList = () => {
    const dispatch = useDispatch();
    const { data, loading, error } =
        useSelector((state) => state.data);
 
    useEffect(() => {
        dispatch(fetchData());
    }, [dispatch]);
 
    if (loading) {
        return <p>Loading...</p>;
    }
 
    if (error) {
        return <p>Error: {error}</p>;
    }
 
    return (
        <div>
            <h2>
                Data List
            </h2>
            <ul>
                {data.map((item) => (
                    <li key={item.id}>
                        {item.title}
                    </li>
                ))}
            </ul>
        </div>
    );
};
 
export default DataList;


Javascript




//fetchDataReducer.js
 
import * as types
    from '../actions/types';
 
const initialState = {
    data: [],
    loading: false,
    error: null,
};
 
const dataReducer = (state = initialState, action) => {
    switch (action.type) {
        case types.FETCH_DATA_REQUEST:
            return {
                ...state,
                loading: true,
                error: null,
            };
        case types.FETCH_DATA_SUCCESS:
            return {
                ...state,
                loading: false,
                data: action.payload,
            };
        case types.FETCH_DATA_FAILURE:
            return {
                ...state,
                loading: false,
                error: action.payload,
            };
        default:
            return state;
    }
};
 
export default dataReducer;


Javascript




//DataActions.js
 
export const FETCH_DATA_REQUEST = 'FETCH_DATA_REQUEST';
export const FETCH_DATA_SUCCESS = 'FETCH_DATA_SUCCESS';
export const FETCH_DATA_FAILURE = 'FETCH_DATA_FAILURE';
 
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 async (dispatch) => {
        dispatch(fetchDataRequest());
        try {
            const response =
                await fetch('https://jsonplaceholder.typicode.com/posts');
            const data =
                await response.json();
            dispatch(fetchDataSuccess(data));
        } catch (error) {
            dispatch(fetchDataFailure(error.message));
        }
    };
};


Javascript




//types.js
 
export const FETCH_DATA_REQUEST = 'FETCH_DATA_REQUEST';
export const FETCH_DATA_SUCCESS = 'FETCH_DATA_SUCCESS';
export const FETCH_DATA_FAILURE = 'FETCH_DATA_FAILURE';
 
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 async (dispatch) => {
        dispatch(fetchDataRequest());
        try {
            const response =
                await fetch('https://jsonplaceholder.typicode.com/posts');
            const data =
                await response.json();
            dispatch(fetchDataSuccess(data));
        } catch (error) {
            dispatch(fetchDataFailure(error.message));
        }
    };
};


Step to Run the App:

npm start

Output:

redux-ezgifcom-video-to-gif-converter

Sample Gif React-Redux App



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads