0

How can I do this? My store is like this:

{
   ...,
   playlist : [
      ...,
      {
          id : 1,
          title :  "fancy-playlist-title",
          songs : [
             { id : 1 },
             { id : 2 },
             ... and so on
          ]
      }
   ]
}

I have this reducer:

if(action.type === "REMOVE_FROM_PLAYLIST"){
        return {
            ...state,
            playlist : [
                ...state.playlist,
                ...state.playlist[action.index].songs.splice(0, action.indexSongs),
                ...state.playlist[action.index].songs.splice(action.indexSongs+1)
            ]
        }
    }

UPDATE

each playlist can have infinite songs, because playlist array contains much objects of playlist like this

playlist : [
   {
      id : 1,
      title : "title",
      songs : []
   },{
     id : 2,
     title : "playlist 2",
     songs : []
   },
   {... and so on}
]

My complete reducer is like this

export default function(state = {}, action) {

if(action.type === "REMOVE_FROM_PLAYLIST"){

        //action.index : current index of playlist
        //action.indexSongs : current index of song that I want to delete from current playlist

        let playlist = state.playlist[action.index].slice(0, action.index).concat(state.playlist[action.index].slice(action.index + 1));
        return {
            ...state,
            playlist : [
                ...state.playlist,
                ...playlist.slice(0, action.indexSongs),
                ...playlist.slice(action.indexSongs + 1)
            ]
        }
    }

return state;
}

My question is how can I delete one song of one playlist? I'm sending the index of current playlist and the index of the song of current playlist.

1
  • just for future - consider using immutable.js - you can more easily manipulate them. Commented Nov 24, 2016 at 9:40

2 Answers 2

4

splice mutates the array state, which you should not be doing.

What you want is a combination of slice and concat:

playlist.slice(0, indexOfSong)  // copy a portion of the array
                                // from the start to the indexOfSong

        .concat(                // concatenate it with:

          playlist.slice(indexOfSong + 1)
                                // copy of a portion of the array from
                                // the index just after indexOfSong
                                // to the end of the playlist
        );

The above can be written using ES6 Spread syntax as follows:

[
  ...playlist.slice(0, indexOfSong)
  ...playlist.slice(indexOfSong + 1));
]

EDIT, considering your recent question update, your reducer should look like this:

export default function(state = {}, action) {

if(action.type === "REMOVE_FROM_PLAYLIST"){
  return {
            ...state,
            playlist : [
                ...state.playlist,
                ...playlist[action.index].songs.slice(0, action.indexSongs),
                ...playlist[action.index].songs.slice(action.indexSongs + 1)
            ]
        }
    }
}
Sign up to request clarification or add additional context in comments.

6 Comments

in this case "concat(list.slice(indexOfSong + 1);", what means list? this.state.playlist[action.index]?, thanks for helping too fast
Typo :) Corrected it now
Thought I'd expand upon this a bit, so added some comments, hope this helps
thanks a lot for your help, but following your code example, i'm getting an error that says "undefined is not a function state.playlist[action.index].slice(0,action.indexOfSong)"
Are you sure state[action.index] resolves to an array? Could you post up your complete reducer? Also check out my alternative syntax using the ES6 spread syntax.
|
1

If you use lodash, you could use _.merge

https://lodash.com/docs/4.17.2#merge

if(action.type === "REMOVE_FROM_PLAYLIST"){
    let newPlaylistWihoutDeletedItem = state.playlist.splice(action.index, 1);

    return _.merge({}, state, {
      playlist: newPlaylistWihoutDeletedItem
    });
}

1 Comment

mutation is not allowed in redux reducers

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.