Redux itself is synchronous, so how the async operations like network request work with Redux?
Here middlewares come handy.
As discussed earlier, reducers are the place where all the execution logic is written.
Reducer has nothing to do with who performs it, how much time it is taking or logging the state of the app before and after the action is dispatched.
Redux middleware function provides a medium to interact with dispatched action before they reach the reducer.
Customized middleware functions can be created by writing high order functions (a function that returns another function), which wraps around some logic.
why Used :
Commonly, middlewares are used to deal with asynchronous actions in your app.
Redux provides with API called applyMiddleware which allows us to use custom middleware as well as Redux middlewares like redux-thunk

Syntax :
applyMiddleware(...middleware)


Ex :import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducers/index';
const store = createStore(rootReducer, applyMiddleware(thunk));