Reputation:
I have created an example for fetching data from API where I used redux-thunk
. The following code is working.
In this context, I want to rewrite my code but using redux saga
.
import React from 'react';
import {createStore, applyMiddleware} from 'redux';
import ReactDOM from "react-dom";
import thunk from 'redux-thunk';
import axios from 'axios';
function App(props) {
const initialState = {
loading: false,
data: [],
error: ''
};
const reducer = function (state = initialState, action) {
switch (action.type) {
case 'START_FETCH':
return {
...state,
loading: true
};
case 'PROCESS_FETCH':
return {
...state,
loading: false,
data: action.payload,
error: ""
};
case 'END_FETCH':
return {
...state,
loading: false,
data: [],
error: action.payload
}
}
return state;
};
const START_FETCH = 'START_FETCH';
const PROCESS_FETCH = 'PROCESS_FETCH';
const END_FETCH = 'END_FETCH';
let startFetchFun = () => {
return {
type: START_FETCH,
loading: true
}
};
let processFetchFun = (users) => {
return {
type: PROCESS_FETCH,
payload: users
}
};
let endFetchFun = (error) => {
return {
type: PROCESS_FETCH,
payload: error
}
};
let fetchUsersWithThunk = () => {
return function (dispatch) {
dispatch(startFetchFun());
axios.get('https://jsonplaceholder.typicode.com/users')
.then((response) => {
dispatch(processFetchFun(response.data));
})
.catch((error) => {
dispatch(endFetchFun(error.message));
console.log(error.message);
})
}
};
const store = createStore(reducer, applyMiddleware(thunk));
store.subscribe(() => {
console.log(store.getState())
});
store.dispatch(fetchUsersWithThunk());
return (
<div className="main">
<h1>Redux-Thunk</h1>
</div>
);
}
ReactDOM.render(
<App/>, document.getElementById('root'));
I want to write the code above using redux saga, to understand better sagas. So, how to use redux-saga for this example? Who will be able to help me?
Upvotes: 3
Views: 16788
Reputation: 5042
Redux Saga uses yield call
to call promises like an api service and uses yield put
to dispatch actions to the store.
The difference is about blocking and not blocking calls.
Because we want to wait for the server to respond our request we will use yield call
that is a blocking function.
Instead of dispatching the action directly inside the generator saga uses yield put({ type: "actionName" })
. That's also useful for testing purposese.
So you should wrote your saga as following:
import {all, fork, put, call, takeLatest} from 'redux-saga/effects';
function* handleRequest (action) {
try {
yield put(startFetchFunc()); // dispatch the action to the store.
const result = yiels call(apiService.users, [data to pass]); // wait for the response blocking the code execution.
yield put(processFetchFun(result)); // dispatch the action to the store containing the data
} catch (e) {
yield put(endFetchFun('Error'));
}
}
function* watchRequest() {
yield takeLatest({type: "START_FETCH"}, handleRequest);
}
export function* rootSaga() {
yield all([
fork(wathcRequest),
// ... more watchers will be here...
]);
}
Congfigure you store as explained here https://redux-saga.js.org/docs/introduction/BeginnerTutorial.html
I suggest you to read the documentation more than once. It contains a lot of useful information that at first might be strange but much clearer once you understand how it works.
Upvotes: 2
Reputation: 1568
You will need to configure your store to use saga middleware:
import React from 'react';
import createSagaMiddleware from 'redux-saga';
import { createStore, applyMiddleware } from 'redux';
import reducer from './reducers';
import rootSaga from './sagas';
const sagaMiddleware = createSagaMiddleware();
const store = createStore(
reducer,
applyMiddleware(sagaMiddleware, logger),
);
sagaMiddleware.run(rootSaga); // < -- rootSaga exports all sagas in your app
Then you can convert your thunk to a saga:
import {call} from 'redux-saga/effects';
function* fetchUsersSaga(payload){
try {
yield call(startFetchFun());
axios.get('https://jsonplaceholder.typicode.com/users')
.then((response) => {
yield call(processFetchFun(response.data));
})
} catch(err) {
yield call(endFetchFun(error.message));
console.log(error.message);
}
};
Upvotes: 1