Goal: After completing this material, you will be able to:
Think of Redux as a delivery service between a restaurant (your component) and the customer (the store). Middleware is like a quality control checkpoint — it inspects, modifies, or even halts the packages (actions) before they reach their destination.
Middleware allows you to:
// Store setup with Redux Thunk and Logger
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import logger from 'redux-logger';
import rootReducer from './reducers';
const store = createStore(
rootReducer,
applyMiddleware(thunk, logger)
);
Explanation: We apply two middlewares here:
thunk to handle async logiclogger to log actions for debuggingImagine Redux Thunk as a translator that allows action creators to speak async language. Normally, action creators return plain objects. With Thunk, they can return functions that delay execution and handle async operations like fetching data.
Real-World Example: Ordering food online — you send a request (fetch), wait for the food (response), then update the UI (dispatch new action).
fetch('https://api.example.com/items')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
Explanation: We request data, wait for it to arrive (asynchronously), then process it.
const fetchItems = () => {
return dispatch => {
dispatch({ type: 'ITEMS_LOADING' });
fetch('https://api.example.com/items')
.then(response => response.json())
.then(data => {
dispatch({ type: 'ITEMS_SUCCESS', payload: data });
})
.catch(error => {
dispatch({ type: 'ITEMS_ERROR', error });
});
};
};
Explanation:
useEffect(() => {
fetch('https://api.example.com/items')
.then(response => response.json())
.then(data => setItems(data));
}, []);
useEffect(() => {
dispatch(fetchItems());
}, [dispatch]);