learningbtw
learningbtw

Reputation: 35

Element is not removed from array

I am trying to delete an actor from actors array which is inside movie object. Firstly, I map actors to display actors one by one and adding a remove action to button. Whole ActorsList component

const PostList = ({ movie, removeActorFromMovie }, props) => {
  return (
    <div>
      <h3>Actors in film </h3>
      {movie.actors.map((actor, i) => (
        <div key={actor}>
          {actor}
          <button onClick={() => removeActorFromMovie(actor)}>Usuń</button>
        </div>
      ))}
    </div>
  );
};

const mapStateToProps = (state, props) => {
  return {
    movie: state.movies.find((movie) => movie.id === props.match.params.id),
  };
};
const mapDispatchToProps = {
  removeActorFromMovie,
};
export default withRouter(
  connect

(mapStateToProps, mapDispatchToProps)(PostList)
);

Action:

export const removeActorFromMovie = (payload) => ({
  type: "MOVIE_ACTOR_DELETE",
  payload,
});

Reducer:

 case "MOVIE_ACTOR_DELETE":
      return [...state.filter((el) => el !== action.payload)];

Although, the payload wokrs great and returns the array item. It does not remove it from an array. My movies array with movie under index 0:

movies: Array(1)
 0:
  actors: (2) ['Robert XYZ', 'Jake XYZ']
  director: "Quentino TARANTINO, TARANTINO"
  id: "352cc51e-87c4-46ec-84a0-9f308ec1a71a"
  productionYear: "123"
  title: "Titanic"

and payload:

payload: "Robert XYZ"
type: "MOVIE_ACTOR_DELETE"

and as I said, this doest not remove the actor from actors array which is under index 0 in movies array

Upvotes: 0

Views: 82

Answers (1)

Antonio Pantano
Antonio Pantano

Reputation: 5042

Update: I'm supposing your state is something like this:

state: {
  movies: [...]
}

If you want to remove an actor from a movie you should also pass the payload a movie to remove the actor from.

removeActorFromMovie(actor, movie) then in the reducer:

const { movie, actor } = action.payload;
const nextMovie = {
  ...movie,
  actors: movie.actors.filter((a) => a !== actor)
};
const movieIndex = state.movies.findIndex((m) => m.id === movie.id);
return {
    ...state,
    movies: [
      ...state.movies.slice(0, movieIndex),
      nextMovie,
      ...state.movies.slice(movieIndex + 1)
    ]
};



OLD ANSWER (If you instead want to remove a movie):

If you want to remove a movie based on its actors you filter function will not work. You are trying to remove an item whose value is "Robert XYZ" but the element passed to you filter function is a movie.

if the state is like this:

movies: [
  {
  actors: ['Robert XYZ', 'Jake XYZ']
  director: "Quentino TARANTINO, TARANTINO"
  id: "352cc51e-87c4-46ec-84a0-9f308ec1a71a"
  productionYear: "123"
  title: "Titanic"
  }
]

then you can do:

const nextItems = state.filter(movie => !movie.actors.includes(action.payload))
return nextItems;

There is no need to create a new copy of the filtered array with the spread operator because filter return a new copy of the original array.

Upvotes: 1

Related Questions