Push to the state array in redux using axios

Viewed 118

I have an array of objects called episodes which looks like this:

"episodes": [
    {
      "title": "XYZ",
      "release_date": "2022-01-08",
      "series": "Breaking Bad",
      "img": "https://upload.wikimedia.org/wikipedia/en/0/03/Walter_White_S5B.png",
      "characters": [], // to this i want to add characters
      "id": 2
    }
  ]

The characters is an array, to which i want to add characters which were in this episode. I want to add multiple characters, not just one and also im adding them one by one. I tried it with the code below, although im using axios.put in my updateEpisode action, so after trying to add the second characters, it rewrites current array. I do not know how to make this code work properly, so instead of changing the existing data, it would push a new character( only the id of an character to be precise) Here are my components and maybe you somehow will come up with a solution. My Form used to add a character:

const AddActorMovie = () => {
  const { episode } = useSelector((state) => state.episodes);
  const { users } = useSelector((state) => state.data);
  const [state, setState] = useState({
    characters: [],
  });
  const [error, setError] = useState("");
  let { id } = useParams();

  let history = useHistory();
  let dispatch = useDispatch();
  const { characters } = state;

  useEffect(() => {
    dispatch(getSingleEpisode(id));
  }, []);

  useEffect(() => {
    if (episode) {
      setState({ ...episode });
    }
  }, [episode]);

  const handleInputChange = (e) => {
    let { name, value } = e.target;
    setState({ ...state, [name]: value });
  };

  const handleSubmit = (e) => {
    e.preventDefault();
    if (!characters) {
      setError("Please input all input Field");
    } else {
      console.log("state tutaj", state);
      dispatch(updateEpisode(state, id));
      history.push("/");
      setError("");
    }
  };
  return (
    <div>
      <button
        variant="contained"
        color="secondary"
        type="button"
        onClick={() => history.push("/")}
      >
        Go Back
      </button>
      <h2>Edit User</h2>
      {error && <h3 style={{ color: "red" }}>{error}</h3>}
      <form onSubmit={handleSubmit}>
        <br />
        <select
          id="standard-basic"
          label="characters"
          value={characters}
          name="characters"
          onChange={handleInputChange}
        >
          <option value="pietrek"> piterek</option>
          {users.map((char) => (
            <option value={char.id}>{`${char.name}`}</option>
          ))}
        </select>

        <button
          variant="contained"
          color="primary"
          type="submit"
          onChange={handleInputChange}
        >
          Update
        </button>
      </form>
    </div>
  );
};

export default AddActorMovie;

Now actions

export const updateEpisode = (episode, id) => {
  return function (dispatch) {
    axios
      .put(`http://localhost:5000/episodes/${id}`, episode)
      .then((resp) => {
        console.log("resp", resp);
        dispatch(episodeUpdated());
      })
      .catch((error) => console.log(error));
  };
};

const episodeUpdated = () => ({
  type: types.UPDATE_EPISODE,
});

AND Reducer:

const initialState = {
  episodes: [],
  episode: {},
  loading: true,
};

const episodesReducer = (state = initialState, action) => {
  switch (action.type) {
    case types.GET_EPISODES:
      return {
        ...state,
        episodes: action.payload,
        loading: false,
      };

    case types.UPDATE_EPISODE:
      return {
        ...state,
        loading: false,
      };
    case types.GET_SINGLE_EPISODE:
      return {
        ...state,
        episode: action.payload,
        loading: false,
      };
    default:
      return state;
  }
};
1 Answers

You don't pass any parameters to episodeUpdated(), so nothing can ever get updated.

I guess you just removed you failed attempts to simplify your code example, with good intentions, but it makes it harder to refer to your code.

Anyway, I assume your state in AddActorMovie is my episodeCharacters below:

case types.UPDATE_EPISODE:
  const { episodeCharacters, id } = action.payload;

  return {
    ...state,
    episodes: state.episodes.map( episode => {
      if( episode.id === id ){      // found id
        return {
          ...episode,               // copy other properties
          characters: [
            ...episode.characters,           // copy existing characters
            ...episodeCharacters.characters, // add new characters
          ]
        };
      } else {
        return episode;   // not the requested id
      }
    }),
    loading: false,
  };
Related