What are common pitfalls to avoid when modifying state with createSlice in Redux-Toolkit?

I am currently working with the createSlice function, specifically with the reducer setCustomEquipment that updates the state. My question is whether the = method is an acceptable way to update the state when using createSlice, or if I should always use the shallow state copy method regardless of whether createSlice is being utilized or not?

export const someSlice = createSlice({
  name: 'some',
  initialState,
  reducers: {
    setCustomEquipment: (state, action: PayloadAction<CustomEquipment[]>) => {
      // Option A 
      state.customEquipment = action.payload;

      // Option B
      // return {
      // ...state, { state.customEquipment : action.payload }
      // }
    },

Answer №1

Whichever approach you choose to use is perfectly acceptable and entirely up to you.

Modify state in place

setCustomEquipment: (state, action: PayloadAction<CustomEquipment[]>) => {
  state.customEquipment = action.payload;
}

Creating a new state reference with shallow copy

setCustomEquipment: (state, action: PayloadAction<CustomEquipment[]>) => {
  return {
    ...state,
    customEquipment: action.payload,
  };
}

When working with Redux-Toolkit slice reducers, you can either directly update the state or return a new state reference (shallow copy). For more information, check out Direct State Mutation.

To simplify things, createReducer utilizes immer to allow you to write reducers as if you were mutating the state directly. The reducer receives a proxy state that translates modifications into copy operations.

Writing "mutating" reducers makes the code cleaner, shorter, and helps reduce common mistakes when handling nested state. However, using Immer introduces some "magic" and has its own nuances. It's important to review the pitfalls mentioned in the immer documentation. The key point is to either modify the state argument directly or return a new state, not both.

One of the pitfalls mentioned is:

Avoid reassigning the draft argument

Never reassign the draft argument (e.g., draft = myCoolNewState). Instead, make modifications to the draft or return a new state.

The common anti-patterns include:

  • Modifying draft state object and returning a new state reference

    setCustomEquipment: (state, action) => {
      state.otherPropery = "foo";
    
      return {
        ...state,
        property: action.payload,
      };
    }
    
  • Reassigning the current state draft object

    setCustomEquipment: (state, action) => {
      state = {
        ...state,
        otherPropery: "foo",
        property: action.payload,
      };
    }
    

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

Require type parameter to be of enum type

I have a specific goal in mind: // first.ts export enum First { One, Two, Three } // second.ts export enum Second { One, Two, Three } // factory.ts // For those unfamiliar, Record represents an object with key value pairs type NotWorkingType ...

Troubles with applying Global Themes in StyledComponents for React Native

Problem with Global Theme in StyledComponents (React Native) When attempting to utilize a color from my global theme in my component and setting it like so: background-color: ${({theme}) => theme.} The properties within theme, such as colors, font-siz ...

Expanding function parameter types using intersection type in Typescript

As I delve into the world of intersection types to enhance a function with an incomplete definition, I encountered an interesting scenario. Take a look at this code snippet: WebApp.connectHandlers.use("/route", (req:IncomingMessage, res:ServerResponse)=& ...

Why am I encountering issues accessing a child property in TypeScript?

Here is some TypeScript code that I am working with: export interface SelectQuery_thing { __typename: "ThingQueryPayload"; content: (SelectQuery_thing_content | null)[]; pageInfo: SelectQuery_thing_pageInfo; } export interface SelectQuery_thing_con ...

Implementing dynamic webpage updates based on dropdown list selections

In my webpage, I am displaying a list of movies fetched from an API. The issue I am facing is related to sorting the movies based on user selection. When I uncomment one of the sort methods in my code, it works as intended. What I want to achieve is that ...

Unable to locate the specified nested module during the import process

Imagine a scenario where we have two packages, namely package1 and package2. When package2 attempts to import the module from package1, an error is thrown stating that the module is not found. The import statement in question looks like this: import { ... ...

Animating sprites using TypeScript

I've been tackling the development of a small Mario game lately. However, I'm facing some difficulty when it comes to animating sprites. For instance, I have a mario.gif file featuring running Mario (although he's not actually running in th ...

Instructions for enabling the touch slider feature in the Igx carousel component with Angular 6 or higher

Looking to enable the touch slider for Igx carousel using angular 6+? I am trying to implement the igx carousel for image sliding with reference from a stackblitz demo (https://stackblitz.com/edit/github-j6q6ad?file=src%2Fapp%2Fcarousel%2Fcarousel.compone ...

Redirecting to login on browser refresh in Angular using Firebase's canActivate feature

An Angular 5 authentication application using angularfire2 and Firebase has been developed. The app functions correctly when navigating through in-app links. However, an issue arises when refreshing the browser, as it redirects back to the Login page even ...

Encountering a frozen UI when navigating can be resolved by incorporating redux-persist with React

As I navigate through the app, I encounter a problem where the UI gets stuck even though the URL changes. I wanted to include redux-persist in my current app, but it led me to encounter an unfamiliar bug. Just a heads up: I am also using redux-saga as mi ...

What is the best way to set up an empty {[key: string]: string} object in TypeScript?

interface a { d: {[key: string]: string} } class a { d = {} } The error message returned is as follows: Subsequent property declarations must have the same type. Property 'd' must be of type '{ [key: string]: string; }', but ...

A secure way to perform a deep update on any type, even if it is completely different from the original

Is there a method to eliminate the as any in the update_substate function? It seems type-safe when directly invoking the update_state function, so it should also be safe when invoked indirectly, right? These functions are meant to be lightweight helpers ...

Having trouble getting webpack to transpile typescript to ES5?

Despite following official guides and various tutorials, I am still facing an issue with compiling my code to ES5 using TypeScript and webpack. The problem is that the final bundle.js file always contains arrow functions. Here is a snippet from my webpack ...

What is the best way to retrieve data from within a for loop in javascript?

Seeking assistance in Typescript (javascript) to ensure that the code inside the for loop completes execution before returning I have a text box where users input strings, and I'm searching for numbers following '#'. I've created a fun ...

Efficiently Measuring the Visibility Area of DetailsList in Fluent UI

I am currently utilizing the DetalisList component alongside the ScrollablePane to ensure that the header remains fixed while allowing the rows to scroll. However, I have encountered a challenge as I need to manually specify the height of the scrollable co ...

Uncover the mystery behind the return value of a generic function in TypeScript

I can't seem to wrap my head around why TypeScript is behaving in the way described below. Snippet 01| const dictionary: { [key: string]: unknown} = {} 02| 03| function set<T>(key: string, value: T): void { 04| dictionary[key] = value; 05| } ...

Having difficulty modifying the redux store when trying to manipulate the initial state

Encountering a violation error while attempting to update a specific componentId in the redux initial state. The error message reads: Uncaught Invariant Violation: A state mutation was detected between dispatches, in the path "currentActivityJSON.dragge ...

Returning a value with an `any` type without proper validation.eslint@typescript-eslint/no-unsafe-return

I am currently working on a project using Vue and TypeScript, and I am encountering an issue with returning a function while attempting to validate my form. Below are the errors I am facing: Element implicitly has an 'any' type because expression ...

How is it possible for the output to be a string array when the variable was declared as a number in TypeScript?

Snippet: function sampleFunction(sample:string|number|string[]) { if(typeof sample == "string") { console.log("Sample is String " + sample); } else if(typeof sample == "number") { console.log("Sample is Number " + sampl ...

A step-by-step guide on how to simulate getMongoRepository in a NestJS service

Struggling with writing unit tests for my service in nestjs, specifically in the delete function where I use getMongoRepository to delete data. I attempted to write a mock but couldn't get it to work successfully. Here is my service: async delete( ...