Open In App

How to handle server-side errors in Redux applications ?

Last Updated : 19 Feb, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

It is essential to deal with server-side errors while building reliable Redux applications. This ensures a seamless user experience, even if problems occur during server requests. This guide will explain the effective management of server errors in the Redux architecture through Redux Thunk middleware and structured error handling techniques.

Handling Server-Side Errors in Redux Applications:

  • Redux Thunk: Redux Thunk is middleware that allows you to write action creators that return a function instead of an action object. This is useful for handling asynchronous logic, such as making API requests to a server.
  • Error Handling Action: Define a specific action type, like FETCH_ERROR, to handle server errors. This action should include relevant information about the error, such as error messages or status codes.
  • Dispatch Actions: When a server error occurs during a request, dispatch the FETCH_ERROR action from your Redux action creator. Pass along any relevant error information as a payload to the action.
  • Reducer: Update the Redux store’s state in the corresponding reducer function to reflect the error status. For example, you might set a error flag to true and store the error message or status code.
  • UI Feedback: Update your UI components to display user-friendly feedback when an error is detected. This could include displaying an error message to the user or rendering a specific error component.
  • Optional: Retry Logic: Depending on your application’s requirements, you may choose to implement retry logic for failed requests. This could involve automatically retrying the request after a certain amount of time or providing users with the option to retry the request manually.
  • Logging: It’s important to log server errors for debugging and monitoring purposes. You can use tools like console.log or specialized logging libraries to log errors to the console or a server-side logging service.

Example: Below is the example of handling server-side Errors in Redux Applications:

Javascript




// index.js
import React from 'react';
import { createRoot } from 'react-dom/client';
import { Provider } from 'react-redux';
import App from './App';
import store from './store';
 
const root = createRoot(document.getElementById('root'));
 
root.render(
  <Provider store={store}>
    <App />
  </Provider>
);


Javascript




// App.js
import React,
{ useEffect } from 'react';
import {
    useDispatch,
    useSelector
} from 'react-redux';
import { fetchData } from './actions/actions';
 
 
const App = () => {
    const dispatch = useDispatch();
    const { loading, data, error } =
        useSelector(state => state);
 
    useEffect(() => {
        dispatch(fetchData());
    }, [dispatch]);
 
    return (
        <div>
            {loading && <p>Loading...</p>}
            {data && (
                <div>
                    <h1>Data</h1>
                    <p>{JSON.stringify(data)}</p>
                </div>
            )}
            {error && <p>Error: {error}</p>}
        </div>
    );
};
 
export default App;


Javascript




// store.js
import {
    createStore,
    applyMiddleware
} from 'redux';
// Correct import
import { thunk }
    from "redux-thunk"
import promiseMiddleware
    from 'redux-promise-middleware';
import { createLogger }
    from 'redux-logger';
import rootReducer
    from './reducers/reducer';
 
// Create logger middleware
const loggerMiddleware = createLogger();
 
// Apply middleware
const store = createStore(
    rootReducer,
    // correct use of thunk 
    applyMiddleware(
        thunk,
        promiseMiddleware,
        loggerMiddleware
    )
);
 
export default store;


Javascript




// actions.js
export const fetchData = () => {
    return async (dispatch) => {
        dispatch({ type: 'FETCH_DATA_PENDING' });
        try {
            const response =
                await fetch('https://dummyjson.com/products');
            const data =
                await response.json();
            dispatch(
                {
                    type: 'FETCH_DATA_FULFILLED',
                    payload: data
                }
            );
        } catch (error) {
            dispatch(
                {
                    type: 'FETCH_DATA_REJECTED',
                    payload: error.message
                });
        }
    };
};


Javascript




// reducers.js
const initialState = {
    loading: false,
    data: null,
    error: null
};
 
const reducer =
    (state = initialState, action) => {
        switch (action.type) {
            case 'FETCH_DATA_PENDING':
                return {
                    ...state,
                    loading: true,
                    error: null
                };
            case 'FETCH_DATA_FULFILLED':
                return {
                    ...state,
                    loading: false,
                    data: action.payload
                };
            case 'FETCH_DATA_REJECTED':
                return {
                    ...state,
                    loading: false,
                    error: action.payload
                };
            default:
                return state;
        }
    };
 
export default reducer;


Output:

gfg35

Output



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads