Using Redux-Saga for Type-Safe Asynchronous Flows
Set up a Redux-Saga example where type checking is enforced in complex asynchronous flows to prevent type issues when dispatching actions after async operations.
import { createStore, applyMiddleware } from 'redux';
import createSagaMiddleware from 'redux-saga';
import { call, put, takeEvery } from 'redux-saga/effects';
import { ActionType, TypedActionCreator } from 'typesafe-actions';
// Define action types
enum ActionTypes {
FETCH_START = 'FETCH_START',
FETCH_SUCCESS = 'FETCH_SUCCESS',
FETCH_FAILURE = 'FETCH_FAILURE'
}
// Define action creators with typesafe-actions
const fetchStart: TypedActionCreator<ActionTypes.FETCH_START> = () => ({
type: ActionTypes.FETCH_START,
});
const fetchSuccess: TypedActionCreator<ActionTypes.FETCH_SUCCESS> = (data: any) => ({
type: ActionTypes.FETCH_SUCCESS,
payload: data,
});
const fetchFailure: TypedActionCreator<ActionTypes.FETCH_FAILURE> = (message: string) => ({
type: ActionTypes.FETCH_FAILURE,
payload: message,
});
// Define the root reducer
const rootReducer = (state = {}, action: ActionType<typeof fetchStart | typeof fetchSuccess | typeof fetchFailure>) => {
switch (action.type) {
case ActionTypes.FETCH_SUCCESS:
return { ...state, data: action.payload };
case ActionTypes.FETCH_FAILURE:
return { ...state, error: action.payload };
default:
return state;
}
};
// Define a saga to handle fetching
function* fetchSaga(): Generator {
try {
const data = yield call(apiFetch); // Replace 'apiFetch' with your API call
yield put(fetchSuccess(data));
} catch (error) {
yield put(fetchFailure(error.message));
}
}
// Root saga
function* rootSaga() {
yield takeEvery(ActionTypes.FETCH_START, fetchSaga);
}
// Setup saga middleware
const sagaMiddleware = createSagaMiddleware();
// Create store with saga middleware
const store = createStore(
rootReducer,
applyMiddleware(sagaMiddleware)
);
// Run the root saga
sagaMiddleware.run(rootSaga);
export { store, fetchStart, fetchSuccess, fetchFailure };
// This code sets up a redux store with saga middleware, using type-safe actions to fetch data asynchronously. The saga handles fetch side effects, capturing both success and failure cases.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Redux-Saga Type-Safe Example</title>
<script src="/path/to/your/compiled-redux-saga-code.js"></script>
</head>
<body>
<div id="app">
<!-- Content will be managed by React/Redux etc. -->
</div>
</body>
</html>
// This is the HTML structure where Redux-Saga will be used. The actual Redux-Saga logic would be in a separate JavaScript file included with a script tag.
body {
font-family: 'Arial', sans-serif;
}
#app {
margin: 20px;
padding: 20px;
border: 1px solid #ccc;
}
// Basic CSS for the #app to make it visually distinct with some padding and a border.