How to make state iterable and resolve "Unhandled Rejection (TypeError): state.story is not iterable"?

Viewed 763

I send a number of files and some other data via redux and axios to my backend. However, when I do so, I get the following error message Unhandled Rejection (TypeError): state.story is not iterable. Although the error occurs in my react js fronted, the data is successfully sent to my backend. When i send normal key vlaue pairs and no array it also works fine.

I now wonder how i can make state.story iterable? Or more general how to approach that issue?

// creating the form data
onClickUpload (e){
  let files = this.state.image;
  let formData = new FormData();

  formData.append('title', "Some_Title")

  for (var i = 0; i < files.length; i++) {
    formData.append(`story_media[${i}]isTitlePicture`, files[i].isTitlePicture)
    formData.append(`story_files[${i}]files`, files[i].file)
  }

    this.props.addStory(formData);

}
// ADD Story Action
export const addStory = formDataStory => (dispatch, getState) =>
new Promise((resolve, reject) => {
  axios.post(apiBase +"/story/createupdatedestroy/", formDataStory, tokenConfig(getState) )
    .then(res => {
      dispatch(createMessage({ addStory: "Story Added" }));
      dispatch({
        type: ADD_STORY,
        payload: res.data
      });
      resolve(res);
    })
    .catch(err => {
      reject(err);
      dispatch(returnErrors(err.response.data, err.response.status))
    }
  );
// Add STory Reducer
const initialState = {
  story: [],
  isFetching: "idle"
};

export default function (state = initialState, action) {
  switch (action.type) {
case GET_STORY_REQUEST:
      return {
        ...state,
        isFetching: "loading"
      };

case GET_STORY_SUCCESS:
      return {
        ...state,
        story: action.payload,
        isFetching: "success"
      };

case GET_STORY_FAILURE:
      return {
      isFetching: "failure"
      };

case GET_SINGLE_STORY:
     return {
        ...state,
        story: state.story.filter(story => story.id !== action.payload)
      };

case DELETE_STORY:
      return {
        ...state,
        story: state.story.filter(story => story.id !== action.payload)
      };

case EDIT_STORY:
      return {
        ...state,
        story: state.story.filter(story => story.id  !== action.payload)
      };


case ADD_STORY:
      return {
        ...state,
        story: [...state.story, action.payload]
      };



    default:
      return state;
  }
}
1 Answers

Issue

One of your reducer cases is not copying the state object correctly. It neglects to copy current state into the new state object.

case GET_STORY_FAILURE:
  return {
    isFetching: "failure"
  };

Solution

Copy existing state into the new state object.

case GET_STORY_FAILURE:
  return {
    ...state,
    isFetching: "failure"
  };
Related