Example Idea Redux thunk is needed for asynchronous calls, such as data fetching. Thunk middleware allows for an action creator function to return a function instead of an action object. Redux-thunk does is a middleware that looks at every action that passes through the system, and if it’s a function, it calls that function. Great explanation what the thunk is. Basic 'action creator' function. function userLoggedIn() { return { type: 'USER_LOGGED_IN', username: 'dave' }; } // use it with dispatch dispatch(userLoggedOut()) Thunk version function logOutUser() { return function(dispatch, getState) { return axios.post('/logout').then(function() { // pretend we declared an action creator // called 'userLoggedOut', and now we can dispatch it dispatch(userLoggedOut()); }) } } // use it with dispatch dispatch(logOutUser()).then(() => { // do something after logout }) Thunks can dispatch new actions if they need to and access the current state. Installation npm install redux-thunk Reducer const initialState = { loading: false, users: [], err: '' } const users = (state = initialState, action) => { switch (action.type) { case 'FETCH_USERS_REQUEST': return { ...state, loading: true } case 'FETCH_USERS_SUCCESS': return { loading: false, users: action.payload, err: '' } case 'FETCH_USERS_FAILURE': return { loading: false, users: [], err: action.payload } default: return state } } const rootReducer = combineReducers({ users }) Action creators const fetchUsersRequest = () => ({ type: 'FETCH_USERS_REQUEST' }) const fetchUsersSuccess = (users) => ({ type: 'FETCH_USERS_SUCCESS', payload: users }) const fetchUsersFailure = (err) => ({ type: 'FETCH_USERS_FAILURE', payload: err }) const fetchUsers = () => { return (dispatch) => { dispatch(fetchUsersRequest()) axios.get('https://jsonplaceholder.typicode.com/users') .then(sleeper(1000)) .then(res => dispatch(fetchUsersSuccess(res.data))) .catch(err => dispatch(fetchUsersFailure(err.message))) } } Store const middlewares = [thunk] const store = createStore( rootReducer, composeWithDevTools( applyMiddleware(...middlewares) ) ) Component const style = { border: '2px solid grey', padding: '10px', margin: '10px', maxWidth: '500px' } function Component() { const users = useSelector(state => state.users) const dispatch = useDispatch() return ( <div style={style}> <button onClick={() => dispatch(fetchUsers())}>Fetch users</button><br /> <div> {users.loading && 'Loading...'} {users.err && users.err} {!users.loading && !!users.users.length && users.users.map(user => <div key={user.id}>{user.name}</div>)} </div> </div> ) } Whole code import { combineReducers, createStore, applyMiddleware } from 'redux' import { Provider, useSelector, useDispatch } from 'react-redux' import { composeWithDevTools } from 'redux-devtools-extension' import thunk from 'redux-thunk' import axios from 'axios' import sleeper from '/functions/sleeper' // #region REDUCERS (sets and changes state) const initialState = { loading: false, users: [], err: '' } const users = (state = initialState, action) => { switch (action.type) { case 'FETCH_USERS_REQUEST': return { ...state, loading: true } case 'FETCH_USERS_SUCCESS': return { loading: false, users: action.payload, err: '' } case 'FETCH_USERS_FAILURE': return { loading: false, users: [], err: action.payload } default: return state } } const rootReducer = combineReducers({ users }) // #endregion // #region ACTION CREATORS const fetchUsersRequest = () => ({ type: 'FETCH_USERS_REQUEST' }) const fetchUsersSuccess = (users) => ({ type: 'FETCH_USERS_SUCCESS', payload: users }) const fetchUsersFailure = (err) => ({ type: 'FETCH_USERS_FAILURE', payload: err }) const fetchUsers = () => { return (dispatch) => { dispatch(fetchUsersRequest()) axios.get('https://jsonplaceholder.typicode.com/users') .then(sleeper(1000)) .then(res => dispatch(fetchUsersSuccess(res.data))) .catch(err => dispatch(fetchUsersFailure(err.message))) } } // #endregion // #region STORE const middlewares = [thunk] const store = createStore( rootReducer, composeWithDevTools( applyMiddleware(...middlewares) ) ) // #endregion // #region Component const style = { border: '2px solid grey', padding: '10px', margin: '10px', maxWidth: '500px' } function Component() { const users = useSelector(state => state.users) const dispatch = useDispatch() return ( <div style={style}> <button onClick={() => dispatch(fetchUsers())}>Fetch users</button><br /> <div> {users.loading && 'Loading...'} {users.err && users.err} {!users.loading && !!users.users.length && users.users.map(user => <div key={user.id}>{user.name}</div>)} </div> </div> ) } // #endregion