简体   繁体   中英

Any tips for mutating the state using redux-toolkit

I'm using redux-toolkit and React. I know basic redux (not using redux-toolkit) aren't allowed to mutate the original state. That's why I chose redux-toolkit to be able to do it. However,I can't understand what's a forbidden way to mutate the state using redux-toolkit. I read an offical document below but it didn't work to me.

https://redux-toolkit.js.org/usage/immer-reducers

Especially Immer Usage Patterns in the document.What's the difference between Mutating and Returning state and Resetting and Replacing state? It looks like similar. Plus, I can't figure out Updating Nested Data in the document.

could you tell me any tips for using redux-toolkit?

The intro of the page you've linked to effectively covers a bit of history for how Redux reducer functions worked in that past. Redux state is considered to be immutable, so if you wanted to update any part of a slice's state you necessarily needed to shallow copy all state and nested state that you wanted to update.

See Reducers and Immutable State :

 function handwrittenReducer(state, action) { return {...state, first: {...state.first, second: {...state.first.second, [action.someId]: {...state.first.second[action.someId], fourth: action.someValue, }, }, }, } }

Redux-Toolkit comes with immer baked right in, so we can write mutable reducer functions and know we are only editing a draft copy of the state that will get applied in an immutable way.

You are interested in the Immer Usage Patterns , specifically Mutating and Returning State .

In any given case reducer, Immer expects that you will either mutate the existing state, or construct a new state value yourself and return it, but not both in the same function! For example, both of these are valid reducers with Immer:

 const todosSlice = createSlice({ name: 'todos', initialState: [], reducers: { todoAdded(state, action) { // "Mutate" the existing state, no return value needed state.push(action.payload) }, todoDeleted(state, action.payload) { // Construct a new result array immutably and return it return state.filter(todo => todo.id.== action.payload) } } })

You can either mutate a part of the state and the change will be correctly applied or you can return an entirely new state object with as much or as little of it updated as you need. The only thing that is forbidden is to mutate part of the existing state and return a new state object reference.

Forbidden update:

const todosSlice = createSlice({
  name: 'todos',
  initialState: {todos: [], status: 'idle'}
  reducers: {
    todoDeleted(state, action.payload) {
      // Construct a new array immutably
      const newTodos = state.todos.filter(todo => todo.id !== action.payload);

      // "Mutate" the existing state to save the new array
      state.todos = newTodos;

      return {
        ...state,
        status: 'complete',
      };
    }
  }
});

Acceptable update:

const todosSlice = createSlice({
  name: 'todos',
  initialState: {todos: [], status: 'idle'}
  reducers: {
    todoDeleted(state, action.payload) {
      // Construct a new array immutably
      const newTodos = state.todos.filter(todo => todo.id !== action.payload);

      // "Mutate" the existing state to save the new array
      state.todos = newTodos;
      state.status = 'complete';
    }
  }
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM