Skip to content

Instantly share code, notes, and snippets.

@ozziexsh
Last active July 13, 2021 05:05
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ozziexsh/4873e4a561489f2ee5b6f216e5513c81 to your computer and use it in GitHub Desktop.
Save ozziexsh/4873e4a561489f2ee5b6f216e5513c81 to your computer and use it in GitHub Desktop.
Redux-Saga Generator Example
import { call, put, takeLatest } from 'redux-saga/effects'
import axios from 'axios'
export const FETCH_API_REQUEST = 'FETCH_API_REQUEST';
export const FETCH_API_SUCCESS = 'FETCH_API_SUCCESS';
export const FETCH_API_FAIL = 'FETCH_API_FAIL';
// Moved api call into own function (for easy test swapping)
export function fetchFromApi(userId) {
return axios.get(`/users/${userId}`)
}
export function* requestFetchFromApi(action) {
try {
const data = yield call(fetchFromApi, action.userId);
yield put(fetchApiSuccess(data));
} catch (error) {
yield put(fetchApiFail(error));
}
}
// Regular action creators
export function fetchApiRequest(userId) {
return {
type: FETCH_API_REQUEST,
userId
}
}
export function fetchApiSuccess(data) {
return {
type: FETCH_API_SUCCESS,
data
};
}
export function fetchApiFail(error) {
return {
type: FETCH_API_FAIL,
error
};
}
// The saga that gets imported and ran by your store
// Listens for all dispatches of FETCH_API_REQUEST
export function* watchRequestFetchApi() {
yield takeLatest(FETCH_API_REQUEST, requestFetchFromApi);
}
import { createStore, combineReducers, applyMiddleware, compose } from 'redux'
import createSagaMiddleware from 'redux-saga'
// Reducers
import someReducer from './SomeReducer' // This can be whatever, redux-saga doesn't change how you make your reducers
// Sagas
import { watchRequestFetchApi } from './Actions'
// For redux devtools
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const sagaMiddleware = createSagaMiddleware();
const reducer = combineReducers({
someState: someReducer
});
const store = createStore(
reducer,
composeEnhancers(
applyMiddleware(sagaMiddleware)
)
);
sagaMiddleware.run(watchRequestFetchApi);
export default store;
import * as Actions from './Actions'
import { call, put } from 'redux-saga/effects'
describe('Saga', () => {
it('should call the api on first action dispatch, and dispatch a success action', () => {
const iterator = Actions.requestFetchFromApi({ userId: 1 });
// Assert that it called the api
expect(iterator.next().value).toEqual(call(Actions.fetchFromApi, 1));
// Assert that it dispatched the success action because the api didn't return an error code
const data = {};
expect(iterator.next(defaults).value, put(Actions.fetchApiSuccess(data)));
});
it('should call the api on first action dispatch, and dispatch a fail action', () => {
const iterator = Actions.requestFetchFromApi({ userId: 'asdf' });
// Assert that it called the api
expect(iterator.next().value).toEqual(call(Actions.fetchFromApi, 'asdf'));
// Assert that it dispatched the fail action because the api call threw an error
const error = {};
expect(iterator.throw(error).value, put(Actions.fetchApiFail(error)));
});
});
@davidtranjs
Copy link

So useful for newbie redux-saga like me, thanks a lot !!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment