Posted by
The Code Post
on
- Get link
- X
- Other Apps
Redux Saga
Redux-Saga is a library written in JavaScript that facilitates state management and managing side effects in React applications. Here are some key points about what Redux-Saga does:
- Side Effect Management: It manages side effects such as API calls, timeouts, and other asynchronous operations.
- Clean and Testable Code: It makes the code written to manage side effects cleaner and more testable.
- Asynchronous Operations: It manages asynchronous operations more easily with Redux actions.
- Flexible Control: It provides greater control over capturing and processing actions.
- Manageable Flows: It makes complex flows and business logic more manageable.
Redux-Saga works using generator functions, providing developers with great flexibility in managing complex asynchronous workflows in their applications. For example, you can use Redux-Saga to send a specific action when making an API call, and then send different actions based on whether the call is successful or fails.
Redux-Saga Example
An application where a switch button sends the light status to the backend and updates the switch status when a positive response is received from the backend:
1. App.js
import React, { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { toggleLightRequest } from './redux/actions';
function App() {
const dispatch = useDispatch();
const lightStatus = useSelector(state => state.lightStatus);
const loading = useSelector(state => state.loading);
const handleToggle = () => {
dispatch(toggleLightRequest(!lightStatus));
};
return (
<div>
<h1>Light Status: {lightStatus ? 'On' : 'Off'}</h1>
<button onClick={handleToggle} disabled={loading}>
{loading ? 'Updating...' : 'Change Status'}
</button>
</div>
);
}
export default App;
2. redux/actions.js
export const TOGGLE_LIGHT_REQUEST = 'TOGGLE_LIGHT_REQUEST';
export const TOGGLE_LIGHT_SUCCESS = 'TOGGLE_LIGHT_SUCCESS';
export const TOGGLE_LIGHT_FAILURE = 'TOGGLE_LIGHT_FAILURE';
export const toggleLightRequest = (status) => ({
type: TOGGLE_LIGHT_REQUEST,
payload: status,
});
export const toggleLightSuccess = (status) => ({
type: TOGGLE_LIGHT_SUCCESS,
payload: status,
});
export const toggleLightFailure = () => ({
type: TOGGLE_LIGHT_FAILURE,
});
3. redux/reducer.js
import { TOGGLE_LIGHT_SUCCESS, TOGGLE_LIGHT_FAILURE, TOGGLE_LIGHT_REQUEST } from './actions';
const initialState = {
lightStatus: false,
loading: false,
error: null,
};
export const lightReducer = (state = initialState, action) => {
switch (action.type) {
case TOGGLE_LIGHT_REQUEST:
return { ...state, loading: true };
case TOGGLE_LIGHT_SUCCESS:
return { ...state, lightStatus: action.payload, loading: false };
case TOGGLE_LIGHT_FAILURE:
return { ...state, loading: false, error: 'Could not update light status.' };
default:
return state;
}
};
4. redux/sagas.js
import { takeLatest, call, put } from 'redux-saga/effects';
import { TOGGLE_LIGHT_REQUEST, toggleLightSuccess, toggleLightFailure } from './actions';
function* toggleLightSaga(action) {
try {
const response = yield call(apiToggleLight, action.payload); // Send request to the backend
if (response.ok) {
yield put(toggleLightSuccess(action.payload)); // Update status if successful
} else {
yield put(toggleLightFailure());
}
} catch (error) {
yield put(toggleLightFailure());
}
}
function apiToggleLight(status) {
return fetch('/api/toggle-light', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ status }),
});
}
export default function* rootSaga() {
yield takeLatest(TOGGLE_LIGHT_REQUEST, toggleLightSaga);
}
5. redux/store.js
import { createStore, applyMiddleware } from 'redux';
import createSagaMiddleware from 'redux-saga';
import { lightReducer } from './reducer';
import rootSaga from './sagas';
const sagaMiddleware = createSagaMiddleware();
const store = createStore(lightReducer, applyMiddleware(sagaMiddleware));
sagaMiddleware.run(rootSaga);
export default store;
6. index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import App from './App';
import store from './redux/store';
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
Backend Example (/api/toggle-light)
app.post('/api/toggle-light', (req, res) => {
const { status } = req.body;
// Add backend logic here (e.g., save to database)
res.json({ success: true });
});
In this example, there is a switch button in App.js. When pressed, the light status is sent to the backend through Redux-Saga, and if the operation is successful, the status of the button is updated.
Information Flow
The information flow in this example occurs as follows:
-
App.js
dispatch(toggleLightRequest(!lightStatus));
→ When the button is pressed, theTOGGLE_LIGHT_REQUESTaction inactions.jsis dispatched. -
redux/actions.js
The toggleLightRequest function is called.
→return { type: TOGGLE_LIGHT_REQUEST, payload: status };sends the new status tolightReducerinredux/reducer.js. -
redux/reducer.js
ThelightReducercaptures theTOGGLE_LIGHT_REQUESTaction fromactions.js.
→ Theloadingstatus is updated totrue. -
redux/sagas.js
ThetakeLatest(TOGGLE_LIGHT_REQUEST, toggleLightSaga)captures theTOGGLE_LIGHT_REQUESTaction fromactions.js.
→ ThetoggleLightSagafunction runs. -
redux/sagas.js
const response = yield call(apiToggleLight, action.payload);
→ TheapiToggleLightfunction is called to send a request to the backend. -
redux/sagas.js
function apiToggleLight(status)
→ A POST request is made to/api/toggle-lightusing thefetchAPI. -
Backend (/api/toggle-light)
app.post('/api/toggle-light', (req, res) => {...})
→ The incoming request is processed, and the light status is saved. -
Backend (continuation)
res.json({ success: true });
→ A success response is returned. -
redux/sagas.js
if (response.ok) { yield put(toggleLightSuccess(action.payload)); }
→ When a successful response is received, theTOGGLE_LIGHT_SUCCESSaction inactions.jsis dispatched. -
redux/reducer.js
ThelightReducercaptures theTOGGLE_LIGHT_SUCCESSaction fromactions.js.
→ The light status is updated, and theloadingstatus is set tofalse. -
App.js
→ When the Redux state is updated, the component re-renders.
→ The light status and button status are updated (the text on the button changes).
Comments
Post a Comment