dipik
[=]
Story Works Experience Contact Blogs

Standard approach for writing Redux logic

12 Jun, 2023

After createStore and configureStore I found something new in RTK that is createSlice. The key attraction is forget about spread and concerns on mutating state. Here we can find reducers and extraReducers. The reducers field is designed for handling synchronous actions, while extraReducers is typically used for handling asynchronous actions, especially those created with createAsyncThunk. I have created a Redux toolkit slice for the projects. This is something that I inspired from crud operations.

export const projectSlice = createSlice({
    name: 'project',
    initialState,
    reducers: {
        index: (state, action) => {
            state.projects = action.payload
        },
        show: (state, action) => {
            state.project = action.payload
        },
        create: (state, action) => {
            state.projects = state.projects.concat([action.payload])
        },
        edit: (state, action) => {
            state.project = action.payload
        },
        update: (state, action) => {
            state.projects = state.projects.map(project =>
                project.id === action.payload.id ? action.payload : project
            );
        },
        remove: (state, action) => {
            state.projects = state.projects.filter(project => project.id !== action.payload.id)
        },
    },
});

The initial state is not undefined. For now, I am hard coding it with two projects you could delete and modify it.

const initialState = {
    projects: [
        { id: 1, title: "Project One" },
        { id: 2, title: "Project Two" },
    ],
    project: {},
    loading: false
};

While play around with these projects, application allow you to create new projects and modify it. These changes are specifically for your local machine. You need to add Thunk middleware to your Redux toolkit slice for loading projects from the server. Thunks are functions that can contain asynchronous logic and can dispatch multiple actions. Here's how you can modify your code to include a Thunk for loading projects:

export const fetchProjects = createAsyncThunk('project/fetchProjects', async () => {
    try {
        const response = await axios.get('http://127.0.0.1:8000/api/project');
        return response.data;
    } catch (error) {
        throw error;
    }
});

Here extraReducers will came to scene. Your createslice can modify by adding this extra field. This is just a part of createSlice function. It allows you to handle actions outside the scope of the normal reducer.

extraReducers: (builder) => {
        builder
            .addCase(fetchProjects.pending, (state) => {
                state.loading = true;
            })
            .addCase(fetchProjects.fulfilled, (state, action) => {
                state.projects = action.payload;
                state.loading = false;
            })
            .addCase(fetchProjects.rejected, (state, action) => {
                console.error('Error fetching projects:', action.error);
                state.loading = false;
            });
    },

Here you can see three cases. The createAsyncThunk function generates three action types: pending, fulfilled, and rejected. These correspond to the different states of an asynchronous operation.

fetchProjects.pending: Dispatched when the asynchronous operation starts.

fetchProjects.fulfilled: Dispatched when the asynchronous operation is successfully completed.

fetchProjects.rejected: Dispatched when the asynchronous operation encounters an error.

This is only the case of fetchProjects similarly you can create async thunk for store, update and delete project.

author

Author

This is a test user.

Explore

JS
React
Redux

Related Read

author
A compact utility for manage immutable state

© 2025 DIPIK. All rights reserved.