Struggling to fix TypeScript error related to Redux createSlice function

Here is the code snippet I am working on:

import { Conversation } from "@/types/conversation";
import { PayloadAction, createSlice } from "@reduxjs/toolkit";

const initialState: Conversation | null = null;

export const conversationSlice = createSlice({
  name: "conversation",
  initialState,
  reducers: {
    setConversation: ( // encountering a type error here
      state: Conversation | null,
      action: PayloadAction<Conversation>
    ) => {
      state = action.payload;
      return state;
    },
  },
});

// Action creators are generated for each case reducer function
export const { setConversation } = conversationSlice.actions;

export default conversationSlice.reducer;

I'm facing an error with the following message:

Type '(state: Conversation | null, action: PayloadAction<Conversation>) => Conversation' is not assignable to type 'CaseReducer<null, { payload: any; type: string; }> | CaseReducerWithPrepare<null, PayloadAction<any, string, any, any>>'.
  Type '(state: Conversation | null, action: PayloadAction<Conversation>) => Conversation' is not assignable to type 'CaseReducer<null, { payload: any; type: string; }>'.
    Type 'Conversation' is not assignable to type 'void'.ts(2322)

I understand that immer is used internally by createSlice. Removing the return statement from setConversation removes the error but causes issues with the reducer functionality. Leaving it as it is results in the error mentioned.

How can I resolve this issue?

I attempted to eliminate the return statement and also referred to the redux toolkit documentation.

The error still persists:

import { Draft, PayloadAction, createSlice } from "@reduxjs/toolkit";

interface Conversation {
  any_data: string[];
}
const initialState: Conversation | null = null;

export const conversationSlice = createSlice({
  name: "conversation",
  initialState,
  reducers: {
    setConversation: (
      // encountered a type error
      state: Draft<Conversation | null>,
      action: PayloadAction<Conversation>
    ) => action.payload,
  },
});

// Action creators are generated for each case reducer function
export const { setConversation } = conversationSlice.actions;

export default conversationSlice.reducer;

Playground

Answer №1

In RTK reducers, it is not allowed to reassign state directly by doing something like state = action.payload. You can either mutate the draft state or return the new state value, but not both at the same time.

I believe that making the conversation state non-nullable would be a better approach. This way, the UI won't have to check if the state is defined or null before accessing its properties. Instead, by making the conversation state properties optional, the UI can simply perform a null-check on the specific property it needs.

Here is an alternative implementation:

import { PayloadAction, createSlice } from "@reduxjs/toolkit";

interface Conversation {
  any_data?: string[];
}
const initialState: Conversation = {};

export const conversationSlice = createSlice({
  name: "conversation",
  initialState,
  reducers: {
    setConversation: (state, action: PayloadAction<Conversation>) => {
      return action.payload;
    },
  },
});

export const { setConversation } = conversationSlice.actions;

export default conversationSlice.reducer;

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

In Javascript, you can compare an array with a nested array and then store the values in a new array

Two arrays are at hand const arrayOne = [ {id: '110'}, {id: '202'}, {id: '259'} ]; const arrayTwo = [ {data: [{value: 'Alpha', id: '001'}]}, {data: [{value: 'Bravo', id: '202'}]}, ...

Can we prevent a component from being mounted every time it is rendered by its parent component?

Is it possible to render the Child component within the Father component without mounting it and resetting its states when the Father component is rendered? I attempted to use the useMemo hook to render the Child component, but it still mounts the compone ...

Stripping double quotes from json output

Using a basic array to reference icons like so: {name: "text", avatar: srcs[15]} has been working perfectly. However, I am now dynamically creating an array from my JSON API, resulting in an array of objects structured like this: {name: "text", avatar: ...

The checkbox is not updating as anticipated

I'm currently developing a basic widget that allows the user to change the value of either the check box OR the entire div by selecting them. Below is the code I have implemented: $(document).ready(function() { $(document).on("click", ".inputChec ...

"Exploring the Power of Logarithmic Slider with Vue and Quasar

I'm currently working on a project utilizing Vue 2 and Quasar 1, where I am attempting to develop a logarithmic slider. Initially, I managed to create a basic example using a native input slider in this code pen: https://codepen.io/tonycarpenter/pen/Z ...

Angular 14 Custom Validator Assistance

I need help understanding how to incorporate a custom validator in my reactive form. I have 15 fields, and 3 of them are related to the custom validators "tcpPorts", "udpPorts", and "icmp" (a checkbox). The requirement is that at least one of these three f ...

Tips for utilizing the onload attribute alongside the ng-controller directive to run a function that has been established within the controller

When trying to call the submit() function as soon as the page loads, I keep encountering a submit() method not found error. The positioning of ng-controller and onload is confusing to me. If there is an alternate method in Angular to achieve this, please ...

Looking to showcase initial API data upon page load without requiring any user input?

Introduction Currently, I am retrieving data from the openweatherAPI, which is being displayed in both the console and on the page. Issue My problem lies in not being able to showcase the default data on the frontend immediately upon the page's fir ...

"Enhabling tablesorter pagination to ensure that buttons always stay in sync with

I am experiencing an issue with the pagination buttons staying at the bottom of my page, even when there are only 2 entries left on the last page. Check out my table here: Is there a way to make the pagination buttons dynamically move to the top based on ...

Tips for utilizing functions in an inline HTML translation pipe

My objective is to streamline the code by using the Angular translate pipe. Currently, I find myself using 8 curly brackets and repeating the word "translate" twice... there must be a more efficient approach. Here is my current code setup: <s ...

Knockout.js dropdown pre-selection in nested JavaScript objects is functioning smoothly in KO 2x versions, but there seems to be a compatibility issue with KO 3x versions

This is a sample data that will be loaded from the server in JSON format and constructed into the below object graph. It consists of an array of "Choice" objects, each with properties like id, name, stages, & currentStageId. The "stages" property in th ...

Discovering the row that was clicked: A step-by-step guide

Hello, I have created a table using JavaScript and now I am looking to determine the row and column that the user has clicked on. Below is the function I am using to generate the table: function doNextSteps() { removeAustriaFromCountries(); //i ...

Encountering a Login Issue with Firebase Google Authentication in Angular 16

I am currently working on implementing a Google sign-in/login feature in Angular 16 using Firebase. However, when I try to click the "LogIn" button, I encounter the following error: "ERROR Error: Uncaught (in promise): TypeError: Cannot read properties of ...

Storing Array Data in Angular $scope (Javascript)

I am currently altering the Altair Material Design Template and incorporating an Angular JS controller. After successfully calling an API and creating variables in a for loop, I intend to write them to $scope.dragulaItems. While this process seems to work ...

Can you explain the variances between the index.html and index-async.html files within the AngularJS seed project?

Within the angularjs seed project, there are two files that appear to produce identical results: index.html and index-async.html. If you want to view the code for index-async.html, you can visit this link. Similarly, if you're interested in the code ...

Accessing an element by its ID with the help of a looping

Looking to retrieve a string from my database and insert it into my paragraphs: <p id="q_1"></p> <p id="q_2"></p> The following code works correctly: $.get("bewertung/get/1", function (data) { document.getElementById("q_1") ...

Obtaining the 3D point coordinates from UV coordinates on a 3D plane object using Three.js

I am in the process of creating basic data visualizations using Three.js as my tool of choice. I have a series of PlaneGeometry meshes to which I am applying a transparent texture dynamically generated with red squares drawn at varying opacity levels. My g ...

Interacting with a form input by triggering the onChange event

I am encountering a problem where I need to be able to select a radio button both onChange via keydown and mouse click. However, I am struggling with accessing both event parameters of the on keydown and on mouse click within the same function. As a result ...

The server mistakenly sent the resource as a Stylesheet even though it was interpreted differently

Dear Fellow Coders, Could anyone lend a hand? I encountered this issue on my website after uploading it to my FTP: "Resource interpreted as Stylesheet but transferred with MIME type text/plain" </head> <body> <div class= "navbar navbar ...

Apply CSS styles when the text exceeds the size of the textbox

Is there a way to create a textbox that scrolls on hover only if the text is longer than the textbox itself? Check out my attempt here: https://jsfiddle.net/SynapticError/wqh4ts3n/35/ The text should scroll on hover if it's longer than the textbox. ...