Boris K
Boris K

Reputation: 3580

React-Redux: deleting an item does not re-render the array

I'm deleting invitations by passing their IDs to the back end, which works. However, my reducer is not working properly to re-render the new, filtered array of invitations. When I refresh the page, the deleted invitation is gone. What am I doing wrong?

The action:

export function deleteInvitation(id) {
    const user = JSON.parse(localStorage.getItem('user'));
    console.log('now deleting id ', id);
    return function(dispatch) {
        axios
            .delete(`${ROOT_URL}/invitation/`, {
                headers: { authorization: user.token },
                params: { id: id }
            })
            .then(response => {
                console.log(id);
                dispatch({
                    type: DELETE_INVITATION,
                    id
                });
            });
    };
}

The reducer:

export default function(state = {}, action) {
    switch (action.type) {
        case INVITATION_SUCCESS:
            return { ...state, invited: true, error: {} };
        case INVITATION_FAILURE:
            return { ...state, invited: false, error: { invited: action.payload } };
        case FETCH_INVITATIONS:
            return { ...state, invitations: action.payload };
        case DELETE_INVITATION:
            return {
                ...state,
                invitations: state.invitations.filter(_id => _id !== action.id)
            };
        default:
            return state;
    }
}

Upvotes: 1

Views: 1668

Answers (1)

Brett DeWoody
Brett DeWoody

Reputation: 62881

I'm making a guess about the structure of the invitations array...

In the reducer, the filter function appears to be incorrect. The action is passing an id property, which I'm guessing is a property of an invitation object. But the filter function is filtering objects from state.invitations where the object is the id. That is, the reducer is doing something like this:

const action = {id: 0}

const invitation = [{
    _id: 0,
    name: 'Name 0',
    location: 'Location 0'
  },
  {
    _id: 1,
    name: 'Name 1',
    location: 'Location 1'
  },
  {
    _id: 2,
    name: 'Name 2',
    location: 'Location 2'
  }
];

console.log(invitation.filter(_id => _id !== action.id));

which will return the full original array because the filter function is checking for the inequality of action.id (a number) to an invitation (an object). Basically:

{
  _id: 0,
  name: 'Name 0',              !===       number
  location: 'Location 0'
}

will return true for any num and/or any invitation object, so the filter function will return every item in state.invitations.

To correct this, check the invitation._id against the action.id, like this:

const action = {id: 0}

const invitation = [{
    _id: 0,
    name: 'Name 0',
    location: 'Location 0'
  },
  {
    _id: 1,
    name: 'Name 1',
    location: 'Location 1'
  },
  {
    _id: 2,
    name: 'Name 2',
    location: 'Location 2'
  }
];

console.log(invitation.filter(invitation => invitation._id !== action.id));

Upvotes: 1

Related Questions