Q:

How to apply async react redux middleware

I'm a beginner in react.
I'd like to use the react redux to request api.
Error: Actions must be plain objects. Use custom middleware for async actions. An error has occurred.
Please help me with any problems.
I'd like to ask you how redux middleware should be applied.
action/index.js
export const fetchActionMovies = async () => {
  const request = await axios.get(`${BASE_URL}/discover/movie?api_key=${API_KEY}&with_genres=28`)

  return {
    type: FETCH_ACTION_MOVIES,
    payload: request
  }
}

reducers/reducerActionMovies.js
import { FETCH_ACTION_MOVIES } from '../actions/index';

export default function (state = {}, action) {
  switch (action.type) {
    case FETCH_ACTION_MOVIES:
      const data = action.payload.data.results;
      return { ...state, data }
    default:
      return state;
  }
}

container/ActionMovie.jsx
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { fetchActionMovies } from '../store/actions/index';

const ActionMovies = () => {

    const dispatch = useDispatch();
    const fetch = dispatch(fetchActionMovies());
    console.log(fetch);

    return (
        <div>
            <h1>Action Movies</h1>
        </div>
    )
}

export default ActionMovies;

index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import * as serviceWorker from './serviceWorker';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import { composeWithDevTools } from 'redux-devtools-extension';
import ReduxThunk from 'redux-thunk';
import rootReducer from './store/reducers';

const store = createStore(
    rootReducer,
    composeWithDevTools(applyMiddleware(ReduxThunk))
    );

ReactDOM.render(
    <Provider store={store}><App /></Provider>,
    document.getElementById('root')
);

serviceWorker.unregister();

Error: Actions must be plain objects. Use custom middleware for async actions.

A:

First, even if you're going to use redux-thunk, you need to break up your action into three parts to track the asynchronous state of the request.
const FETCH_ACTION_MOVIES_REQUEST = "FETCH_ACTION_MOVIES_REQUEST";
const FETCH_ACTION_MOVIES_SUCCESS = "FETCH_ACTION_MOVIES_SUCCESS";
const FETCH_ACTION_MOVIES_FAILURE = "FETCH_ACTION_MOVIES_FAILURE";

You should create three actions that use these types that your reducer will track. Now, if you're not going to use redux-thunk... you will need to perform this fetch in your component. However, if you are using redux-thunk you can create an action like this:

export const fetchActionMovies = () => dispatch => {
  dispatch(fetchActionMoviesRequest());
  return axios.get(`${BASE_URL}/discover/movie?api_key=${API_KEY}&with_genres=28`).then(({
    data
  }) => {
    dispatch(fetchActionMoviesSuccess(data));
  }).catch(error => {
    dispatch(fetchActionMoviesFailure(error));
  })
}

