Error: Actions must be plain objects. Use custom m

2019-02-26 04:43发布

问题:

Below is the code for my action creator:

export function fetchPosts()
  {
    const request = axios.get(`${ROOT_URL}/posts${API_KEY}`);
    return
      {
        type: FETCH_POSTS;
        payload: request

      };
  }

Next to type: FETCH_POSTS, if i add , instead of ; i get the error Unexpected token. Is that the syntax for action creators?

Then if i replace , with ; upon compile i get the error 'Actions must be plain Javascript Objects.

Any idea why?

回答1:

GibboK's answer has already pointed out the syntax error.

However, I don't think you understand using actions properly. You run:

const request = axios.get(`${ROOT_URL}/posts${API_KEY}`);

This is creating a promise. You are currently returning this in an action. Reducers are meant to be deterministic & side effect free, hence why actions should be plain JS objects. You should not be submitting a promise.

Instead, you should be using some relevant middleware, e.g. redux-thunk, redux-saga or something else. You should send an action when the actual promise has resolved.

As a simple contrived example, using redux-thunk:

export const fetchPosts = () => (dispatch) => {
    // Send action to notify request started. Reducers often want to
    // update the state to record that a request is pending, e.g. for
    // UI purposes.
    dispatch({type: FETCH_POSTS_START});

    // Start request
    request = axios.get(`${ROOT_URL}/posts${API_KEY}`)
       .then(res => { 
          // Successfully received posts, submit response data
          dispatch({type: FETCH_POSTS_COMPLETE, payload: res.data})
        })
       .catch(err => { 
          // API call failed, submit error
          dispatch({type: FETCH_POSTS_ERROR, payload: err})
        });
};

Note this code is just an example and not necessarily suitable for use in a production system.



回答2:

When you replace , with ; you get an error because, as stated by your error message, an action must return a JavaScript object.

In JavaScript object properties should be separated by , as:

return
      {
        type: FETCH_POSTS, // use comma here
        payload: request   
      };

In this way the return statement will return a new object with two properties type and payload.



回答3:

As per redux documentation:

Actions are plain JavaScript objects. Actions must have a type property that indicates the type of action being performed. Types should typically be defined as string constants. Once your app is large enough, you may want to move them into a separate module.

And Action Creators

Action creators are functions that create actions

In Redux action creators simply return an action:

function addTodo(text) {
  return {
    type: ADD_TODO,
    text
  }
}

So when you call the action creator from your component through dispatch your action creator just needs to simply return a plain javascript object.

So a normal action creator will be

export function fetchPosts()
  {

    return
      {
        type: FETCH_POSTS;
        payload: "somevalue"

      };
  }

Now if you want to call APIs within your action creators you need to make use of middlewares like redux-thunk or redux-saga while creating a store

like

import thunk from 'redux-thunk';
const store  = createStore(reducers, applyMiddleware(thunk));

You you configure your store with middleware you can modify your actions to

export function fetchPosts() {
    return (dispatch) =>  {   
        axios.get(`${ROOT_URL}/posts${API_KEY}`)
               .then((response)=> {
                     dispatch( {
                           type: FETCH_POSTS,
                           payload: request

                     })
                })  
        } 

     }

As per the redux-thunk documentation

Why Do you need redux-thunk?

Redux Thunk middleware allows you to write action creators that return a function instead of an action. The thunk can be used to delay the dispatch of an action, or to dispatch only if a certain condition is met. The inner function receives the store methods dispatch and getState as parameters.