React native with redux-saga

React native with redux-saga

For a good application where lots of API calls are going to happen simultaneously and many calculations take place, we need a robust project architecture, So we can have the flexibility to manage API calls from anywhere in the application and data as we needed, as we know that in react application when we use redux, we have another option for API call is to use redux-thunk which help as to make async network calls, but problem is there, the action got impure, because their network calls are made in action, so there Redux-Saga comes in role

The difference between Redux-Thunk and Redux-Saga is, Redux-Thunk based upon the action dispatch, where is redux-saga work as action watcher and work independently to action.

Application data flow after configured to redux-saga
redux_saga
Installation

npm install --save redux-saga

actions will reaming as it is Actions.js

import {
	FETCHING_CONFIG,
	FETCHING_CONFIG_SUCCESS,
	FETCHING_CONFIG_FAILURE,
} from 'AppRoot/src/constants';

export function fetchConfig() {
	return {
		type: FETCHING_CONFIG
	};
}
export function fetchConfigSuccess(payload) {
	return {
		type: FETCHING_CONFIG_SUCCESS,
		payload
	};
}
export function fetchConfigError(payload) {
	return {
		type: FETCHING_CONFIG_FAILURE,
		payload
	};
}

there is no change in reducer also Reducer.js

import {
	FETCHING_CONFIG,
	FETCHING_CONFIG_SUCCESS,
	FETCHING_CONFIG_FAILURE,
} from 'appRoot/constants';

const initialState = {
	config: {
		payload: {},
		loading: false,
		error: null
	}
};

export default function mainReducer(state = initialState, action) {
	switch (action.type) {
		case FETCHING_CONFIG:
			let config = { ...state.config };
			config.loading = true;
			config.error = null;
			return {
				...state,
				config
			};
		case FETCHING_CONFIG_SUCCESS:
			config = { ...state.config };
			config.loading = false;
			config.error = null;
			config.payload = action.payload;
			return {
				...state,
				config
			};
		case FETCHING_CONFIG_FAILURE:
			config = { ...state.config };
			config.loading = false;
			config.error = true;
			return {
				...state,
				config
			};
		default:
			return state;
	}
}

To make network calls we need a helper function to handle fetch api call helper.js

    export function makeRequest(url) {
	return fetch(url, options).then(response=>response.json())
    }

Now it is time to so something new, creating your sagas.js

    import { FETCHING_CONFIG } from 'appRoot/constants';
import { makeRequest } from './helper'
import { fetchConfigSuccess, fetchConfigError} from 'appRoot/saga'
import { call, put, takeEvery } from 'redux-saga/effects';

function* fetchConfig(action) {
  try {
    const data = yield call(makeRequest,'yourUrl');
    yield put(fetchConfigSuccess(data));
  } catch (error) {
    yield put(fetchConfigError(error));
  }
}

function* configSaga() {
  yield takeEvery(FETCHING_CONFIG, fetchConfig);
}

export default configSaga;

now we are done with saga implementation, now we need some configuration in existing code.

configure in store.js

import { createStore, applyMiddleware } from 'redux';
// importing your root reducer
import app from 'appRoot/reducers';

import createSagaMiddleware from 'redux-saga';

// importing your root saga
import dataSaga from 'appRoot/sagas';

// creating saga middleware instance
const sagaMiddleware = createSagaMiddleware();

export default function configureStore() {
  const store = createStore(app, applyMiddleware(sagaMiddleware)); //configuring saga
  sagaMiddleware.run(dataSaga);
  return store;
}

there is no any changes need in app.js where provider and store are configured.

Conclusion: By leveraging redux-saga we can make a robust application, redux-saga help when our project grows because it less complex.

Related Article