TransWikia.com

useReducer dispatch executing twice

Stack Overflow Asked by remil on December 7, 2021

I don’t understand why this happens. Since strict mode is enabled in react, this function gets executed twice. So instead of deleting a single item, it deletes two items, one on first round, second on the next.

const deleteItem = (state, index) => {
    // index is a number
       
    let indexCounter = 0;
    let tempArray = [...state.todos];

    const newTodos = tempArray.filter(item => {
        if (item.index === index) {
            return false;
        }
        item.index = indexCounter++;
        return true;
    });

    return {
        ...state,
        todos: newTodos,
        nextIndex: indexCounter
    };   
}

But if I use a Set instead of primitive data type (number), this works fine. i.e. only one item will be removed, even though dispatch is called twice.

const deleteItem = (state, set) => {

    const newSet = new Set(set);
    
    let indexCounter = 0;
    let tempArray = [...state.todos];

    const newTodos = tempArray.filter(item => {
        if (newSet.has(item.index)) {
            newSet.delete(item.index);
            return false;
        }
        item.index = indexCounter++;
        return true;
    });

    return {
        ...state,
        todos: newTodos,
        nextIndex: indexCounter
    };
    
}

Am I missing something here? What exactly is happening?

2 Answers

I've updated the code. It's working fine now. Hope it's correct.

const deleteItem = (state, index) => {

    let indexCounter = 0;

    const tempArray = state.todos.filter(item => {
        return index !== item.index;
    });

    const newTodos = [];
    tempArray.forEach((item) => {
        newTodos.push({...item, index: indexCounter++});
    })

    return {
        ...state,
        todos: newTodos,
        nextIndex: indexCounter
    };
    
}

Answered by remil on December 7, 2021

You are mutating the state which influences the next action.

// Is a shallow copy
let tempArray = [...state.todos];

const newTodos = tempArray.filter((item) => {
  if (item.index === index) {
    return false;
  }
  // State mutation
  item.index = indexCounter++;
  return true;
});

Instead, you need to make a deep copy or use Immutable Update Pattern as mentioned in Redux docs.

Answered by Dennis Vash on December 7, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP