Friday, November 28, 2025

thumbnail

Managing Application State in React with Redux and ASP.NET Core

 Managing Application State in React with Redux and ASP.NET Core


When building modern web applications, the React frontend and ASP.NET Core backend must work together smoothly. Redux helps manage complex state on the client, while ASP.NET Core provides APIs and data persistence on the server.


This guide covers how to structure your project, manage client–server state, and keep everything synchronized.


1. What Redux Solves in a React + ASP.NET Core App


React manages UI state, but complex applications often need global state such as:


Authenticated user data


Tokens and session details


Cart or dashboard data


Notifications


Global filters & settings


Data fetched from the ASP.NET Core API


Redux helps:


Store and update state globally


Keep UI consistent


Enable predictable state transitions


Support debugging with Redux DevTools


2. Project Architecture Overview

Frontend (React + Redux Toolkit)


Manages UI state


Calls ASP.NET Core API


Stores global and session state in Redux store


Uses slices to handle features


Backend (ASP.NET Core Web API)


Validates requests


Provides secure endpoints


Returns JSON data


Manages databases (EF Core, SQL Server, PostgreSQL, etc.)


Issues JWT tokens for authentication


3. Setting Up Redux Toolkit


Install Redux Toolkit and React Redux:


npm install @reduxjs/toolkit react-redux


Create the Redux store

// store.js

import { configureStore } from '@reduxjs/toolkit';

import authReducer from './slices/authSlice';

import productsReducer from './slices/productsSlice';


export const store = configureStore({

  reducer: {

    auth: authReducer,

    products: productsReducer

  }

});



Wrap the React app:


import { Provider } from 'react-redux';

import { store } from './store';


root.render(

  <Provider store={store}>

    <App />

  </Provider>

);


4. Using Redux Toolkit Slices

✔ Example: Authentication Slice

// slices/authSlice.js

import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';

import axios from 'axios';


export const login = createAsyncThunk(

  'auth/login',

  async (credentials) => {

    const response = await axios.post('/api/auth/login', credentials);

    return response.data;  // JWT + user info

  }

);


const authSlice = createSlice({

  name: 'auth',

  initialState: {

    user: null,

    token: null,

    status: 'idle'

  },

  reducers: {

    logout(state) {

      state.user = null;

      state.token = null;

    }

  },

  extraReducers: (builder) => {

    builder.addCase(login.fulfilled, (state, action) => {

      state.user = action.payload.user;

      state.token = action.payload.token;

    });

  }

});


export const { logout } = authSlice.actions;

export default authSlice.reducer;



This slice lets Redux manage authentication state, including the JWT returned from ASP.NET Core.


5. Consuming ASP.NET Core API from Redux


Use createAsyncThunk to call backend endpoints.


Example: Fetching products:


// slices/productsSlice.js

export const fetchProducts = createAsyncThunk(

  'products/fetchAll',

  async () => {

    const response = await axios.get('/api/products');

    return response.data;

  }

);



Reducers update the global store when data arrives.


6. Securing API Requests with JWT (ASP.NET Core)

ASP.NET Core Login Endpoint Example

[HttpPost("login")]

public IActionResult Login([FromBody] LoginModel model)

{

    var user = Authenticate(model.Username, model.Password);

    if (user == null) return Unauthorized();


    var token = GenerateJwtToken(user);

    return Ok(new { user, token });

}



Decode the token in React and store it in Redux:


dispatch(login({ username, password }));


7. Adding JWT to Axios Requests (Frontend)


When logged in, attach the token to every request:


axios.interceptors.request.use((config) => {

  const token = store.getState().auth.token;

  if (token) {

    config.headers.Authorization = `Bearer ${token}`;

  }

  return config;

});


8. Keeping Redux and ASP.NET Core in Sync

✔ State that should live in Redux (frontend):


UI state (loading, dialogs, filters)


Logged-in user info


Temporary form data


Cached API responses


✔ State that should live in ASP.NET Core (backend):


Database records


Business rules


Authentication & authorization


Secure data


✔ Synchronization strategy:


Frontend → dispatch action


Redux thunk → calls ASP.NET Core endpoint


ASP.NET Core processes the request and returns data


Redux reducers update the global store


UI re-renders with fresh state


9. Example Workflow: Updating a User Profile

Step 1: User clicks "Save"


React dispatches:


dispatch(updateUser(formData));


Step 2: Thunk calls API

export const updateUser = createAsyncThunk(

  'auth/updateUser',

  async (data) => {

    const response = await axios.put('/api/users/me', data);

    return response.data;

  }

);


Step 3: ASP.NET Core updates database

[Authorize]

[HttpPut("me")]

public async Task<IActionResult> UpdateProfile(UserDto dto)

{

    var user = await _userService.UpdateAsync(dto);

    return Ok(user);

}


Step 4: Redux updates state globally

builder.addCase(updateUser.fulfilled, (state, action) => {

  state.user = action.payload;

});



React UI updates automatically.


10. Best Practices for React + Redux + ASP.NET Core

Frontend


Use Redux Toolkit (not legacy Redux)


Keep UI-only state out of Redux


Handle loading & error states


Store JWT securely (httpOnly cookies recommended)


Use thunks for all API calls


Backend


Use ASP.NET Core Identity or JWT


Validate every request


Use DTOs instead of exposing database models


Enable CORS for your frontend


Log and handle errors consistently


Architecture


Treat Redux as your “client-side source of truth”


Treat ASP.NET Core as the “server-side source of truth”


Avoid duplicating business logic in React


11. Folder Structure Example

Frontend (React)

src/

  app/

    store.js

  slices/

    authSlice.js

    productsSlice.js

  components/

  pages/


Backend (ASP.NET Core)

Controllers/

Services/

Models/

DTOs/

Repositories/

Startup.cs or Program.cs


Summary


Managing application state in a React + Redux + ASP.NET Core app involves:


Using Redux Toolkit for clean, predictable state management


Fetching and updating data through ASP.NET Core Web APIs


Keeping authentication state (JWT) in Redux


Synchronizing server and client state with async thunks


Protecting APIs with JWT and validating on the backend


Using Redux slices to organize features cleanly


This approach provides a scalable, maintainable, and secure architecture.

Learn Dot Net Course in Hyderabad

Read More

Component-Based Development in Blazor

Introduction to TailwindCSS for Full Stack .NET Developers

Implementing Lazy Loading in Full Stack .NET Applications

How to Implement Real-Time Features with SignalR and React

Visit Our Quality Thought Institute in Hyderabad

Get Directions 

Subscribe by Email

Follow Updates Articles from This Blog via Email

No Comments

About

Search This Blog

Powered by Blogger.

Blog Archive