What is @redux-saga/core?
@redux-saga/core is a library that aims to make application side effects (i.e., asynchronous things like data fetching and impure things like accessing the browser cache) easier to manage, more efficient to execute, and better at handling failures. It uses an ES6 feature called Generators to make those asynchronous flows easy to read, write, and test.
What are @redux-saga/core's main functionalities?
Handling Side Effects
This code demonstrates how to handle side effects using @redux-saga/core. The `fetchUser` worker saga performs an asynchronous API call to fetch user data and dispatches actions based on the result. The `mySaga` watcher saga listens for 'USER_FETCH_REQUESTED' actions and triggers the worker saga.
```javascript
import { call, put, takeEvery } from 'redux-saga/effects';
import axios from 'axios';
// Worker saga
function* fetchUser(action) {
try {
const user = yield call(axios.get, `/api/user/${action.payload.userId}`);
yield put({ type: 'USER_FETCH_SUCCEEDED', user: user.data });
} catch (e) {
yield put({ type: 'USER_FETCH_FAILED', message: e.message });
}
}
// Watcher saga
function* mySaga() {
yield takeEvery('USER_FETCH_REQUESTED', fetchUser);
}
export default mySaga;
```
Managing Complex Async Flows
This code demonstrates managing complex asynchronous flows using @redux-saga/core. The `authorize` worker saga handles the login process, and the `loginFlow` watcher saga continuously listens for 'LOGIN_REQUEST' actions and forks the `authorize` saga.
```javascript
import { call, put, take, fork } from 'redux-saga/effects';
import axios from 'axios';
function* authorize(user, password) {
try {
const token = yield call(axios.post, '/api/auth', { user, password });
yield put({ type: 'LOGIN_SUCCESS', token: token.data });
} catch (e) {
yield put({ type: 'LOGIN_FAILURE', message: e.message });
}
}
function* loginFlow() {
while (true) {
const { user, password } = yield take('LOGIN_REQUEST');
yield fork(authorize, user, password);
}
}
export default loginFlow;
```
Testing Sagas
This code demonstrates how to test sagas using @redux-saga/core. The test case verifies that the `fetchUser` saga yields the correct effects when handling a 'USER_FETCH_REQUESTED' action.
```javascript
import test from 'tape';
import { call, put } from 'redux-saga/effects';
import { fetchUser } from './sagas';
import axios from 'axios';
// Test case
test('fetchUser Saga test', (assert) => {
const action = { type: 'USER_FETCH_REQUESTED', payload: { userId: 1 } };
const generator = fetchUser(action);
let next = generator.next();
assert.deepEqual(
next.value,
call(axios.get, '/api/user/1'),
'fetchUser should yield an Effect call(axios.get, "/api/user/1")'
);
const user = { data: { id: 1, name: 'John Doe' } };
next = generator.next(user);
assert.deepEqual(
next.value,
put({ type: 'USER_FETCH_SUCCEEDED', user: user.data }),
'fetchUser should yield an Effect put({ type: "USER_FETCH_SUCCEEDED", user: user.data })'
);
assert.end();
});
```
Other packages similar to @redux-saga/core
redux-thunk
redux-thunk is a middleware that allows you to write action creators that return a function instead of an action. It is simpler and more straightforward compared to @redux-saga/core, but it may not be as powerful for handling complex asynchronous flows.
redux-observable
redux-observable is a middleware for handling side effects in a Redux application using RxJS observables. It is more suitable for applications that already use or plan to use RxJS, offering a different paradigm for managing async flows compared to @redux-saga/core.
rematch
rematch is a Redux framework that abstracts away much of the boilerplate associated with Redux. It includes built-in support for side effects and async actions, making it easier to manage state and side effects compared to @redux-saga/core.