To connect a Product List UI with Redux-Saga in JavaScript, follow this step-by-step flow:
1. Define Actions
// actions/productActions.js
export const fetchProducts = () => ({ type: 'FETCH_PRODUCTS_REQUEST' });
2. Create a Reducer
// reducers/productReducer.js
const initialState = {
loading: false,
products: [],
error: null,
};
export default function productReducer(state = initialState, action) {
switch (action.type) {
case 'FETCH_PRODUCTS_REQUEST':
return { ...state, loading: true };
case 'FETCH_PRODUCTS_SUCCESS':
return { loading: false, products: action.payload, error: null };
case 'FETCH_PRODUCTS_FAILURE':
return { loading: false, products: [], error: action.error };
default:
return state;
}
}
3. Create Saga
// sagas/productSaga.js
import { call, put, takeEvery } from 'redux-saga/effects';
function fetchFromAPI() {
return fetch('/api/products').then(res => res.json());
}
function* fetchProductsSaga() {
try {
const data = yield call(fetchFromAPI);
yield put({ type: 'FETCH_PRODUCTS_SUCCESS', payload: data });
} catch (error) {
yield put({ type: 'FETCH_PRODUCTS_FAILURE', error: error.message });
}
}
export default function* productWatcherSaga() {
yield takeEvery('FETCH_PRODUCTS_REQUEST', fetchProductsSaga);
}
4. Configure Store
// store.js
import { createStore, applyMiddleware, combineReducers } from 'redux';
import createSagaMiddleware from 'redux-saga';
import productReducer from './reducers/productReducer';
import productSaga from './sagas/productSaga';
const sagaMiddleware = createSagaMiddleware();
const rootReducer = combineReducers({ productState: productReducer });
const store = createStore(rootReducer, applyMiddleware(sagaMiddleware));
sagaMiddleware.run(productSaga);
export default store;
5. Connect to UI
// components/ProductList.js
import React, { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { fetchProducts } from '../actions/productActions';
const ProductList = () => {
const dispatch = useDispatch();
const { loading, products, error } = useSelector(state => state.productState);
useEffect(() => {
dispatch(fetchProducts());
}, [dispatch]);
if (loading) return <p>Loading...</p>;
if (error) return <p>Error: {error}</p>;
return (
<ul>
{products.map(p => (
<li key={p.id}>{p.name}</li>
))}
</ul>
);
};
export default ProductList;