Error encountered with the root reducer due to data type mismatch

Within my Redux store setup, I have a persistedReducer initialized to include the redux-persist config and the "rootReducer":

client/src/redux/store.ts:

import { configureStore } from '@reduxjs/toolkit';
import { persistStore, persistReducer } from 'redux-persist';
import storage from 'redux-persist/lib/storage';
import autoMergeLevel2 from 'redux-persist/es/stateReconciler/autoMergeLevel2';
import rootReducer from './rootReducer'

const persistConfig = {
  key: 'root',
  storage,
  stateReconciler: autoMergeLevel2,
}

const persistedReducer = persistReducer(persistConfig, rootReducer)

export const store = configureStore({
  reducer: persistedReducer
});

export const persistor = persistStore(store);
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;

The structure of the rootReducer that is declared and exported can be found in:

client/src/redux/rootReducer.ts:

import { combineReducers } from "@reduxjs/toolkit";
import { IUserState } from "../interfaces/user";
import userSlice from "./features/userSlice";

export interface RootState {
  user: IUserState;
}

const rootReducer = combineReducers({
  user: userSlice.reducer,
});

export default rootReducer;

The userSlice reducer imported into the rootReducer is constructed as follows:

client/src/redux/features/userSlice.ts
:

import { createAsyncThunk, createSlice, PayloadAction } from "@reduxjs/toolkit";
import { IUserState } from "../../interfaces/user";
import { useSelector } from "react-redux";
import userApi from "../../apis/user";
import { RootState } from "../store";

// More code here...

export default userSlice;

The data structure for the user's state is defined in client/src/interfaces/user.ts, like this:

export type IUserState = {
  _id: string
  ipAddress: string
  createdAt: string
  alignment: string
  loading: boolean
  error: string
}

A specific issue arises in the client output concerning types mismatch within the Reducer component, along with a separate error related to the Typescript compiler. These errors seem to stem from the way the RootState interface is defined.

Answer №1

It seems like the main issue lies within your updateUser Thunk, where there are a couple of issues that need addressing.

  1. There is no requirement to parameterize createAsyncThunk as it should automatically deduce the correct types based on the store and payload creator argument.
  2. updateUser is not a React component or custom React hook, so it cannot utilize the useSelector hook. Use thunkApi.getState to access the current state value instead.
  3. The rejectWithValue function should be returned, not thrown, from the Thunk.
export const updateUser = createAsyncThunk<
  IUserState,
  any,
  {
    state: RootState,
    rejectValue: {
      error: string;
    }
  }
>("user/updateUser", (data: any, thunkApi) => {
  try {
    const user = thunkApi.getState().user;
    return userApi.updateUser(user, data);
  } catch (error) {
    return thunkApi.rejectWithValue({ error: "user not updated" });
  }
});

or

export const updateUser = createAsyncThunk(
  "user/updateUser",
  (data: any, thunkApi) => {
    try {
      const user = (thunkApi.getState() as RootState).user;
      return userApi.updateUser(user, data);
    } catch (error) {
      return thunkApi.rejectWithValue({ error: "user not updated" });
    }
  }
);

In addition, there are also issues in the userSlice related to state updates. It is recommended to either mutate the state directly or return an entirely new state reference value. Avoid reassigning the state using

state = Object.assign(state, payload)
, as it can lead to potential problems. Here are some suggestions:

const userSlice = createSlice({
  name: "userData",
  initialState,
  reducers: {
    getUser: (state, action: PayloadAction<IUserState>) => {
      // Mutate state
      Object.assign(state, action.payload);

      // Or return new state value
      // return action.payload;
    },
    updateUser: (state, action: PayloadAction<IUserState>) => {
      // Mutate state
      Object.assign(state, action.payload);

      // Or return new state value
      // return action.payload;
    },
  },
  extraReducers: (builder) => {
    builder.addCase(getUser.fulfilled, (state, action) => {
      Object.assign(state, action.payload);
      state.loading = false;
      state.error = "";
    });
    builder.addCase(getUser.pending, (state) => {
      state.loading = true;
      state.error = "";
    });
    builder.addCase(getUser.rejected, (state, action) => {
      state.loading = false;
      state.error = action.payload || "user not initialized";
    });
  },
});

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Obtaining gender information by utilizing checkboxes in Angular 7

I have developed an Angular application that enables users to filter samples by gender using checkboxes. The options include male, female, or both genders selected. Currently, the filtering works for selecting either male or female individually, as well as ...

Tips for resolving SyntaxError: Unable to utilize import when integrating Magic with NextJS in a Typescript configuration

Looking to integrate Magic into NextJS using TypeScript. Following a guide that uses JavaScript instead of TypeScript: https://github.com/magiclabs/example-nextjs Encountering an issue when trying to import Magic as shown below: import { Magic } from &qu ...

When converting a PDF to a PNG, the precious data often disappears in the process

I am currently facing a problem with the conversion of PDF to PNG images for my application. I am utilizing the pdfjs-dist library and NodeCanvasFactory functionality, but encountering data loss post-conversion. class NodeCanvasFactory { create(w, h) { ...

Leveraging Renderer in Angular 4

Understanding the importance of using a renderer instead of directly manipulating the DOM in Angular2 projects, I have gone through multiple uninstallations, cache clearings, and re-installations of Node, Typescript, and Angular-CLI. Despite these efforts, ...

To avoid TS2556 error in TypeScript, make sure that a spread argument is either in a tuple type or is passed to a rest parameter, especially when using

So I'm working with this function: export default function getObjectFromTwoArrays(keyArr: Array<any>, valueArr: Array<any>) { // Beginning point: // [key1,key2,key3], // [value1,value2,value3] // // End point: { // key1: val ...

Ways to identify modifications from a BehaviorSubject and automatically trigger a response according to the updated value

I am currently implementing a BehaviorSubject for managing languages in my Angular project. I am also utilizing Angular Datatables and trying to dynamically change the language displayed in the data table based on the value returned from the subscription. ...

The assigned type does not match the type 'IntrinsicAttributes & { children?: ReactNode; }'. This property is not assignable

I have been struggling to resolve this issue, but unfortunately, I have not found a successful solution yet. The error message I am encountering is: Type '{ mailData: mailSendProps; }' is causing an issue as it is not compatible with type &apos ...

Tips for successfully importing $lib in SvelteKit without encountering any TypeScript errors

Is there a way to import a $lib into my svelte project without encountering typescript errors in vscode? The project is building and running smoothly. import ThemeSwitch from '$lib/ThemeSwitch/ThemeSwitch.svelte'; The error message says "Canno ...

Ways to implement the flow of change occurrences in the mat-select component

Seeking assistance with utilizing the optionSelectionChanges observable property within Angular Material's mat-select component. This property provides a combined stream of all child options' change events. I'm looking to retrieve the previ ...

Having trouble with NextJS TypeScript and the randomUUID?() function? If you're seeing the error TS2386 that says "Overload signatures must all be

In my project setup, I have a mono-repo structure utilizing Lerna for managing 2 NextJS projects and 1 shared project. I recently attempted to integrate typescript. The NextJS projects seem to be functioning correctly (following the documentation), but I ...

merging pictures using angular 4

Is there a way in Angular to merge two images together, like combining images 1 and 2 to create image 3 as shown in this demonstration? View the demo image ...

There is no index signature that accepts a parameter of type 'string' in the type '{ [key: string]: AbstractControl; }'

I'm currently tackling a challenge in my Angular project where I am creating a custom validator for a reactive form. However, I've encountered an error within the custom validators function that I am constructing. Below you will find the relevan ...

What is the best method for compressing and decompressing JSON data using PHP?

Just to clarify, I am not attempting to compress in PHP but rather on the client side, and then decompress in PHP. My goal is to compress a JSON array that includes 5 base64 images and some text before sending it to my PHP API. I have experimented with l ...

Definition of TypeScript for caching middleware in Express

I recently came across a helpful Medium post that inspired me to create an express middleware function for caching the response. However, I'm facing some challenges while trying to implement it in typescript. Specifically, I am struggling to identify ...

React Typescript: Unable to set component as element

Currently, I am working on mapping my JSX component (Functional Component) inside an object for dynamic rendering. Here's what I have devised up to this point: Interface for Object interface Mappings { EC2: { component: React.FC<{}>; ...

If "return object[value1][value2] || default" does not work, it means that value1 is not a recognized property

Within my code, there is an object literal containing a method that retrieves a sub-property based on a specific input. If the lookup fails, it should return a default property. //private class, no export class TemplateSelection { 'bills'; & ...

What methods can I use to locate the circular dependency within my program?

I am facing numerous circular dependency errors in my Angular project, causing it to malfunction. Is there a way to identify the section of the code where these circular dependencies exist? Warning: Circular dependency detected: src\app&bs ...

Encountering a parsing issue: an unexpected token was found, expecting "," instead

I'm encountering a Parsing error that states: Unexpected token, expected ",". I've been unable to pinpoint where the missing "," is located. Please refer to the image below for the exact line of the error. const cartSlice = createSlice({ name ...

The Typescript Select is displaying an incorrect value

Here's the code snippet I've been working with: <select #C (change)="changeSelect(zone.id, C.value)"> <option *ngFor="let town of townsLocal" [attr.value]="town.data" [attr.selected]="town.data === zone.town && 'selected& ...

Adding a total property at the row level in JavaScript

Here is a JavaScript array that I need help with: [{ Year:2000, Jan:1, Feb: }, {Year:2001, Jan:-1, Feb:0.34 }] I want to calculate the total of Jan and Feb for each entry in the existing array and add it as a new property. For example: [{ Year:2000, Ja ...