Redux-Saga for Complex Async Flow
Set up a Redux-Saga to handle side-effects in a complex application, managing multiple asynchronous operations in a clear and maintainable way.
import { takeLatest, call, put, all, fork } from 'redux-saga/effects';
import api from './api';
// Actions
const FETCH_USERS_REQUEST = 'FETCH_USERS_REQUEST';
const FETCH_USERS_SUCCESS = 'FETCH_USERS_SUCCESS';
const FETCH_USERS_FAILURE = 'FETCH_USERS_FAILURE';
// Action Creators
export const fetchUsersRequest = () => ({ type: FETCH_USERS_REQUEST });
const fetchUsersSuccess = users => ({ type: FETCH_USERS_SUCCESS, payload: users });
const fetchUsersFailure = error => ({ type: FETCH_USERS_FAILURE, payload: error });
// Worker Saga: will be fired on FETCH_USERS_REQUEST actions
function* fetchUsers() {
try {
const users = yield call(api.fetchUsers);
yield put(fetchUsersSuccess(users));
} catch (error) {
yield put(fetchUsersFailure(error.message));
}
}
// Watcher Saga: Spawns a new fetchUsers task on each FETCH_USERS_REQUEST
function* watchFetchUsers() {
yield takeLatest(FETCH_USERS_REQUEST, fetchUsers);
}
// rootSaga combines all the sagas
export default function* rootSaga() {
yield all([
fork(watchFetchUsers),
// Add additional sagas here
]);
}
This is a setup for Redux-Saga with rootSaga combining all watcher sagas including watchFetchUsers, which listens for 'FETCH_USERS_REQUEST' action and triggers fetchUsers worker saga to perform API call.
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import createSagaMiddleware from 'redux-saga';
import rootReducer from './reducers';
import rootSaga from './sagas';
// Redux Store Configuration
const sagaMiddleware = createSagaMiddleware();
const store = createStore(
rootReducer,
applyMiddleware(sagaMiddleware)
);
// Run the root saga
sagaMiddleware.run(rootSaga);
// React Component
function App() {
return (
<Provider store={store}>
{/* Your App Components */}
</Provider>
);
}
export default App;
This is the setup of the Redux store with Saga middleware. It creates the store, applies the sagaMiddleware, and runs the rootSaga to start the Saga processes.
import { useDispatch } from 'react-redux';
import { fetchUsersRequest } from './actions';
function UsersComponent() {
const dispatch = useDispatch();
// Dispatch action to fetch users
const handleClick = () => {
dispatch(fetchUsersRequest());
};
return (
<div>
<button onClick={handleClick}>Load Users</button>
{/* Render users here */}
</div>
);
}
export default UsersComponent;
This example component dispatches a fetchUsersRequest action when a button is clicked. That action is caught by the Redux-Saga watchFetchUsers saga.
body {
background-color: #f3f3f3;
font-family: 'Arial', sans-serif;
}
button {
background-color: #4CAF50;
border: none;
color: white;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin: 4px 2px;
cursor: pointer;
border-radius: 4px;
}
button:hover {
background-color: #45a049;
}
This is the CSS for styling the UsersComponent, giving app a simple look and feel by setting background color and styles for the button.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Redux Saga Demo</title>
<style>
/* Previos CSS code snippet can be pasted here */
</style>
</head>
<body>
<div id="root"></div>
<script src="path_to_bundled_js_file"></script>
</body>
</html>
The HTML file serves as a container for the React application. It includes a root div where the React components will be mounted, and a reference to the bundled JavaScript file that includes the Redux-Saga logic.