user14009873
user14009873

Reputation:

Trying to do a filter method on an object

I'm trying to do a delete todo and I want to remove the item from the object "byIds" with the specific id. It will be like a filter for arrays but for the object. I don't know what's so complicated hope for help I believe its stupid

import { ADD_TODO, TOGGLE_TODO, DELETE_TODO } from "../actionTypes";

const initialState = {
  allIds: [],
  byIds: {},
};

export default function (state = initialState, action) {
  switch (action.type) {
    case ADD_TODO: {
      const { id, content } = action.payload;
      return {
        ...state,
        allIds: [...state.allIds, id],
        byIds: {
          ...state.byIds,
          [id]: {
            content,
            completed: false,
          },
        },
      };
    }
    case TOGGLE_TODO: {
      const { id } = action.payload;
      return {
        ...state,
        byIds: {
          ...state.byIds,
          [id]: {
            ...state.byIds[id],
            completed: !state.byIds[id].completed,
          },
        },
      };
    }
    // of course its toggling but it doesn't even get there
    case DELETE_TODO: {
      const { id } = action.payload;
      return {
        ...state,
        allIds: state.allIds.filter((todo) => todo !== id),
        byIds: state.byIds.filter((todo) => todo !== id),
      };
    }
    default:
      return state;
  }
}

{
  todos: {
    allIds: [
      1,
      2,
      3,
      4
    ],
    byIds: {
      '1': {
        content: 'Test1',
        completed: false
      },
      '2': {
        content: 'Test2',
        completed: false
      },
      '3': {
        content: 'test3',
        completed: false
      },
      '4': {
        content: 'test4',
        completed: false
      }
    }
  },
  visibilityFilter: 'all'
}

That for the one who asked me to console log the byIds hope that will help me

Upvotes: 3

Views: 103

Answers (3)

D. Smith
D. Smith

Reputation: 749

You can separate the id out like this:

case DELETE_TODO: {
  const id = action.payload.id;
  const { [id]: _, ...filteredState } = state.byIds; 
  // ^ this takes id from state and puts it in variable _,
  // everything else is packed into filteredState

  return {
    ...state,
    allIds: state.allIds.filter((todo) => todo !== id),
    byIds: filteredState,
  };
}

Edit: Extra notes for anyone wondering about the syntax above, see these links:

Computed Property Names, how we are grabbing [id]

Destructuring assignment, how we are packing back into ...filteredState

Awesome comment explaining destructuring

Upvotes: 0

Apostolos
Apostolos

Reputation: 10498

What you need is to iterate through the keys of byids object and take only the ones you need.

case DELETE_TODO: {
  const { id } = action.payload;
  let newObj = {}

  Object.keys(state.byIds).forEach(function(key) {
    if (key !== id) {
      newObj[key] = state.byIds[key]
   }
  });
  return {
    ...state,
    allIds: state.allIds.filter((todo) => todo !== id),
    byIds: newObj 
  };
}

In case your id is not a string but a number, you need to check with key != id and not key !== id

Upvotes: 2

Jeff Mercado
Jeff Mercado

Reputation: 134621

You could use the rest syntax to exclude the id when creating the new object.

case DELETE_TODO: {
  const { id } = action.payload;
  const { [id]: _, ...restByIds } = state.byIds;
  return {
    ...state,
    allIds: state.allIds.filter((todo) => todo !== id),
    byIds: restByIds,
  };
}

Upvotes: 0

Related Questions