React-Redux: Actions must be plain objects. Use cu

2020-01-30 11:46发布

问题:

Unhandled Rejection (Error): Actions must be plain objects. Use custom middleware for async actions.

I wanted to add comments with every posts. So when fetch posts are run I want to call fetch comment API for all post.

export function bindComments(postId) {
  return API.fetchComments(postId).then(comments => {
    return {
      type: BIND_COMMENTS,
      comments,
      postId
    }
  })
}

回答1:

Your have to dispatch after async request ends.

This would work:

export function bindComments(postId) {

 return function (dispatch){
   return API.fetchComments(postId).then(comments => {
   // dispatch
     dispatch( {
       type: BIND_COMMENTS,
       comments,
       postId
     })
   })
 }
}


回答2:

You can't use fetch in actions without middleware. Actions must be plain objects. You can use a middleware like redux-thunk or redux-saga to do fetch and then dispatch another action.

Here is an example of async action using redux-thunk middleware.

export function checkUserLoggedIn (authCode) {
 let url = `${loginUrl}validate?auth_code=${authCode}`;
  return dispatch => {
    return fetch(url,{
      method: 'GET',
      headers: {
        "Content-Type": "application/json"
      }
      }
    )
      .then((resp) => {
        let json = resp.json();
       if (resp.status >= 200 && resp.status < 300) {
          return json;
        } else {
          return json.then(Promise.reject.bind(Promise));
        }
      })
      .then(
        json => {
          if (json.result && (json.result.status === 'error')) {
            dispatch(errorOccurred(json.result));
            dispatch(logOut());
          }
          else{
            dispatch(verified(json.result));
          }
        }
      )
      .catch((error) => {
        dispatch(warningOccurred(error, url));
      })
  }
}


回答3:

Make use of Arrow functions it improves the readability of code. No need to return anything in API.fetchComments, Api call is asynchronous when the request is completed then will get the response, there you have to just dispatch type and data.

Below code does the same job by making use of Arrow functions.

export const bindComments = postId => {
  return dispatch => {
    API.fetchComments(postId).then(comments => {
      dispatch({
        type: BIND_COMMENTS,
        comments,
        postId
      });
    });
  };
};