Using Redux on react native (2) — adding Redux Saga

Time:2021-12-1

In the last articleUsing Redux on react native (I) — adding ReduxSuccessfully putreduxAdd to the project, nowredux-sagaAdd in

This articleUsing Redux on react native (3) — adding Redux thunkIs to useredux-thunk, you can compare it with this oneredux-thunkandredux-sagaDifferences in use

Make a second runner this time. ClickstartClick the button to start running secondsstop itClick the button to stop running secondsResetThe button time is cleared. The number is blue in the run second state and black in the stop state

First inpackage.jsonAdd inredux-sagaLibrary and in the directorynpm install:

"dependencies": {
    ...
    "redux-saga": "^0.11.0"
},

holdactionChange the name to make more sense,actionsTypes.js:

export const START = 'START';
export const STOP = 'STOP';
export const RESET = 'RESET';
export const RUN_TIMER = 'RUN_TIMER';

actions.jsChange accordingly:

import { START, STOP, RESET, RUN_TIMER } from './actionsTypes';

const start = () => ({ type: START });
const stop = () => ({ type: STOP });
const reset = () => ({ type: RESET });
const runTime = () => ({ type: RUN_TIMER });

export {
    start,
    stop,
    reset,
    runTime
}

reducers.jsstayactionAfter the change, it also needs to be adjusted:

import { combineReducers } from 'redux';
import { START, STOP, RESET, RUN_TIMER } from './actionsTypes';

//Original default state
const defaultState = {
  seconds: 0,
  runStatus: false
}

function timer(state = defaultState, action) {
  switch (action.type) {
    case START:
      return { ...state, runStatus: true };
    case STOP:
      return { ...state, runStatus: false };
    case RESET:
      return { ...state, seconds: 0 };
    case RUN_TIMER:
      return { ...state, seconds: state.seconds + 1 };
    default:
      return state;
  }
}

export default combineReducers({
    timer
});

Add asagas.jsFile to process the business logic of the project:

import { takeEvery, delay, END } from 'redux-saga';
import { put, call, take, fork, cancel, cancelled } from 'redux-saga/effects';
import { START, STOP, RESET, RUN_TIMER } from './actionsTypes';
import { stop, runTime } from './actions';

function* watchStart() {
  //Generally, take every is replaced by a while loop
  while (true) {
    //Take: wait for the dispatch to match an action
    yield take(START);
    //Usually, fork and cancel are used together to implement non blocking tasks. Take is in blocking status, that is, when taking, it cannot continue to execute downward. Fork is non blocking. You can also use cancel to cancel a fork task
    var runTimeTask = yield fork(timer);
    yield take(STOP);
    //Cancel: cancel a fork task
    yield cancel(runTimeTask);
  }
}

function* watchReset() {
  while (true) {
    yield take(RESET)
    yield put(stop());
  }
}

function* timer() {
  try {
    while(true) {
      //Call: call saga or the function that returns promise in a blocking way, and only trigger an action
      yield call(delay, 1000);
      //Put: trigger an action with the same function as dispatch
      yield put(runTime());
    }
  } finally {
    if (yield cancelled()) {
      Console.log ('runtimetask task canceled ');
    }
  }
}


export default function* rootSaga() {
    yield fork(watchStart);
    yield fork(watchReset)
}

holdsagaAdd as middlewarestore, store.jsAs follows:

import { createStore, applyMiddleware, compose } from 'redux';
import createSagaMiddleware, { END } from 'redux-saga';
import createLogger from 'redux-logger';
import rootReducer from './reducers';
import sagas from './sagas';

const configureStore = preloadedState => {
    const sagaMiddleware = createSagaMiddleware();
    const store = createStore(
        rootReducer,
        preloadedState,
        compose (
            applyMiddleware(sagaMiddleware, createLogger())
        )
    )

    sagaMiddleware.run(sagas);
    store.close = () => store.dispatch(END);
    return store;
}

const store = configureStore();
export default store;

OK, it’s done,commond+Rfunction.