Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

142
Visualizações
Error: An immer producer returned a new value *and* modified its draft. Either return a new value *or* modify the draft

I have my reducer


const userAuthSlice = createSlice({
    name: "userAuth",
    initialState: {
        token: '',
    },
    reducers: {
        setToken: (state, action) => state.token = action.payload.test,
    },
});

And I have my dispatch command

<button
   value={text.sign_in.submit}
   onClick={() => dispatch(userAuthSlice.actions.setToken({test:"test"}))}

/>

As I press the button what I get is this error:

enter image description here

I have isolated everything to be sure that this is the problem and nothing else.

Why does this error pop up?

over 4 years ago · Santiago Trujillo
7 Respostas
Responde à pergunta

0

The issue is the use of an arrow function with no curly braces as the reducer, because that acts as an implicit return statement. So, you're both mutating state.token, and returning the result of the assignment.

Per the Immer docs on returning data, there's a couple ways to fix this:

  • Adding the void operator in front of the assignment
  • Wrapping the assignment in curly braces to make it a function body

so setToken reducer can be updated with void as

setToken: (state, action) => void(state.token = action.payload.test)
over 4 years ago · Santiago Trujillo Relatório

0

Instead of

 state.token = action.payload.token

use

 const token = action.payload.token
 state.token = token

Constants are immutable, and assigning action.payload contents to a constant resolved a problem for me (Note that in case the payload is an object it is not necessary

Working example of createSlice:

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

export const slice = createSlice({
  name: 'login',
  initialState: {
      username: "Foo",
      password: "AAA",
      authorized : false
  },
  reducers: {
    setUsername: (state, action) => {

      const value = action.payload
      state.username = value // action.payload.username

    },
    setPassword: (state, action) => {

      const value = action.payload
      state.password = value // action.payload.password

    },
    logon: (state, action) => {

      state.username = action.payload.username
      state.password = action.payload.password
      state.authorized = true

    },
    logoff: state => state.authorized = false
  },
});
over 4 years ago · Santiago Trujillo Relatório

0

you may forget break; statement at your reducer.js file;

 case LOGIN_USER_ERROR_RESET:
        draft.errormsg = '';
        draft.loading = false;
        draft.error = false;
        break;
over 4 years ago · Santiago Trujillo Relatório

0

Points to learn about IMMER

  1. If you return anything other than draft from the recipe function, that return value will replace the state
  2. You mostly want to mutate the draft to mutate the state, ** so returning draft after modifying it is optional**, the immer will return finalized draft anyway
  3. if you return anything else from recipe function then as per point 1, the new return value will replace the state
  4. Point 3 is ok, only if you do not modify the draft in your recipe function. i.e. you can choose one of the two
    a. modify the draft --> return draft or undefined, either is ok
    b. want to return some new value, then don't touch the draft at all

Now coming to answer for the question. this is your reducer function

(state, action) => state.token = action.payload.test

This function is doing two things,
1. modifying state
2. returning action.payload.test

so it's violating point 4 and hence the error from Immer library

in this specific case, intention is only to modify the state, so we have to undo the existing return with void

setToken: (state, action) => void(state.token = action.payload.test)

However, Immer library recommends the use of code block to insure consistency across large code-base, this code block implicitly returns undefined

setToken: (state, action) => { state.token = action.payload.test } 
over 4 years ago · Santiago Trujillo Relatório

0

Try checking this link for Copying Without Reference

over 4 years ago · Santiago Trujillo Relatório

0

Correct answer

Use Instead of

const userAuthSlice = createSlice({
    name: "userAuth",
    initialState: {
        token: '',
    },
    reducers: {
        setToken: (state, action) => state.token = action.payload.test,
    },
});

Use this {I have just added brackets}

const userAuthSlice = createSlice({
    name: "userAuth",
    initialState: {
        token: '',
    },
    reducers: {
        setToken: (state, action) => { state.token = action.payload.test}, // <<= Change Here
    },
});
over 4 years ago · Santiago Trujillo Relatório

0

For those who are working with React PullState, my issue was with the syntax:

I had:

 const onUpdate = (value: any) => {
    someStore.update((s) => (s.value = value));
 };

but has to be:

 const onUpdate = (value: any) => {
    someStore.update((s) => {
       s.value = value;
    });
 };

For some reason, doesn't like the arrow function declared on the first approach.

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda