Sai Krishnadas
Sai Krishnadas

Reputation: 3409

I get null when i use find in an array - redux

I have 3 actions ( add_todo,delete_todo,completed_todo). Add and delete works fine but I should add the deleted items to the completed list in order to render that in a separate component. But whenever I try to use, filter or find to get the deleted items I get a null value.

Reducer code :

const initialState = {
  todos: [],
  completed: [],
};

const todoSlice = createSlice({
  name: "todos",
  initialState,
  reducers: {
    add_todo(state, action) {
      state.todos = [...state.todos, action.payload];
    },
    delete_todo(state, action) {
      state.todos = state.todos.filter((todo) => todo.id !== action.payload);
    },
    completed_todo(state, action) {
      console.log(state.todos.find((todo) => todo.id === action.payload));
      state.completed = [
        ...state.completed,
        state.todos.filter((todo) => todo.id === action.payload),
      ];
    },
  },
});

export const todoActions = todoSlice.actions;

export const selectTodo = (state) => state.todos.todos;

export default todoSlice.reducer;

code where i call or dispatch my actions:

function TodoList() {
  const dispatch = useDispatch();
  const todos = useSelector(selectTodo);
  const handleDelete = (id) => {
    dispatch(todoActions.delete_todo(id));
    dispatch(todoActions.completed_todo(id));
  };
// Some code and a button with handleDelete 
}

Upvotes: 0

Views: 76

Answers (2)

Shyam
Shyam

Reputation: 5497

The problem here is by the time you are dispatching the action to get the completed list your deleted todo's is already gone from the state . Instead of dispatching 2 actions . you can do what are asking for in the delete todo action .

delete_todo(state, action) {
      // find the todo to delete 
      const deletedTodo = state.todos.find((todo) => todo.id === action.payload);
       state.completed = [
        ...state.completed,
        deletedTodo,
      ];
      state.todos = state.todos.filter((todo) => todo.id !== action.payload);
    },

since your completed todo is nothing but the todo which you are trying to delete . IMHO its logical to do it in the same action which we use to dispatch for deleting a todo .

Upvotes: 1

Martin Seeler
Martin Seeler

Reputation: 6982

The actions will be dispatched one after another. After your first action dispatch(todoActions.delete_todo(id));, you will remove the todo from your state .filter((todo) => todo.id !== action.payload).

After that, the second action get's dispatched dispatch(todoActions.completed_todo(id));. But state.todos.find((todo) => todo.id === action.payload) will not find it, since it is already removed.

To fix it, you could swap your dispatch calls. First complete it, then remove it. Problem solved :-)

Upvotes: 1

Related Questions