N
N
Nikita Shchypylov2018-05-03 17:03:21
React
Nikita Shchypylov, 2018-05-03 17:03:21

Why does Actions must be plain objects occur without ReduxThunk?

Hello everyone
Such an AC for processing an asynchronous request:

export const searchAction = (val:string) => async dispatch => {
  const root:string = "https://images-api.nasa.gov/";
  const res = await axios.get(`${root}/search?q=${val}`);
  return dispatch({
    type: consts.SEARCH_INIT,
    payload: res
  })
};

Error : Uncaught Error: Actions must be plain objects. Use custom middleware for async actions.
But I'm returning an ordinary object in the res variable. Why doesn't the code work without ReduxThunk then?
Thanks

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
Anton Spirin, 2018-05-03
@Nikulio

Because redux-thunk is middleware and if you looked at its sources (14 lines in total), you would see that it intercepts and calls functions, passing the necessary arguments to them and returns the result without betraying it further. Without it, there is nothing to intercept them and they get where they should not go and provoke an error, since Redux without middleware only accepts objects as input to dispatch , which is what the text of the error you get says.
The return value ( return ) in asynchronous actions is used only by you, it is returned by dispatch call. As mentioned above, it does not fall into reducers.
Since a Promise is returned , it can be used something like this:
Your Async action :

export const asyncAction = (...someArgs) => async dispatch => {
  const res = await someAsyncCall(...someArgs);
  dispatch({ type: SOME_ACTION_TYPE, payload: res });

  return res;
};

Usage in code (explicit example with dispatch ):
componentDidMount() {
  const { dispatch } = this.props;

  dispatch(asyncAction(...optionalArgs)).then(result => doSomething(result));
}

The same with forwarding an async action via connect :
componentDidMount() {
  const { asyncAction } = this.props;

  asyncAction(...optionalArgs).then(result => doSomething(result));
}

In general, to use then , it is not necessary to return a value from an asynchronous function, and such code will also work fine:
export const asyncAction = (...someArgs) => async dispatch => {
  const res = await someAsyncCall(...someArgs);
  dispatch({ type: SOME_ACTION_TYPE, payload: res });
};

Usage in code (explicit example with dispatch ):
componentDidMount() {
  const { dispatch } = this.props;

  dispatch(asyncAction(...optionalArgs)).then(() => doSomething());
}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question