[RN][Redux] Redux-saga

Redux Saga

Redux Saga sử dụng cơ chế load dữ liệu bất đồng bộ và các generators để làm cho việc tương tác api trở nên dễ dàng và thú vụ hơn.

"Saga sử dụng tính năng của ES6 là Generators để tạo ra các luồng kết nối bất đồng bộ giúp cho công việc đọc, viết, kiểm thử api được đơn giản hoá. ( và nếu bạn chưa đồng ý với những đánh giá này thì trong bài viết có một số link để cho bạn tham khảo thêm) Và cơ chế xử lý luồng bất đồng bộ này được viết dưới quy chuẩn đồng bộ của ngôn ngữ kịch bản JavaScript. ( một loại giống như assync/await, nhưng các generators có thêm các tính năng awsome mà chúng ta cần)" - Theo tài liệu của Redux Saga.

Để thực thi một Saga, trước hết chúng ta cần update các bước hành động. Trong file actions.js, xoá bỏ hết mọi thứ trừ chức năng bên dưới:

import { FETCHING_DATA } from './constants'

export function fetchData() {
  return {
    type: FETCHING_DATA
  }
}

Hành động này sẽ thực thi saga mà chúng ta tạo ra. Các bạn tạo một file mới saga.js và thêm vào đoạn code sau:

import { FETCHING_DATA, FETCHING_DATA_SUCCESS, FETCHING_DATA_FAILURE } from './constants'
import { put, takeEvery } from 'redux-saga/effects'
import getPeople from './api'

function* fetchData (action) {
  try {
    const data = yield getPeople()
    yield put({ type: FETCHING_DATA_SUCCESS, data })
  } catch (e) {
    yield put({ type: FETCHING_DATA_FAILURE })
  }
}

function* dataSaga () {
  yield takeEvery(FETCHING_DATA, fetchData)
}

export default dataSaga

Chúng ta import constants nếu cần thiết. Ngoài ra chúng ta import phương thức put và takeEvery từ redux-saga/effects. Khi chúng ta gọi phương thức put, redux saga sẽ hướng các phần trung gian (middleware) tới thực thi một hành động. takeEvery là phương thức lắng nghe kết quả trả về của hành động ở trên ( trong trường hợp này của chúng ta là FETCHING_DATA) và gọi về một phương thức cakback ( ở đây là fetchData)

Khi phương thức fetchData đc gọi, Chúng ta sẽ chờ xem nếu như phương thức getPeople trả về thành công thì nó sẽ thực thi hành động FETCHING_DATA_SUCCCESS.

Cuối cùng, chúng ta cần update file configureStore.js để sử dụng saga middleware thay vì sử dụng thunk middleware.

import { createStore, applyMiddleware } from 'redux'
import app from './reducers'

import createSagaMiddleware from 'redux-saga'
import dataSaga from './saga'

const sagaMiddleware = createSagaMiddleware()

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

Nhữg điểm chính cần lưu ý trong file này là nếu chúng ta import saga và cũng createSagaMiddleware từ thư viện redux-saga. Khi chúng ta tạo ra store, chúng ta sẽ pass mọi thứ cho sagaMiddleware mà chúng ta đã tạo ra và gọi sagaMiddleWare.run trước khi mọi thứ được lưu trữ ở store.

Bây giờ, nếu chúng ta có thể chạy ứng dụng và sẽ có kết quả tương tự như khi chúng ta sử dụng redux thunk.

Chú ý rằng nếu 3 files trên được move từ thunk qua saga đó là saga.js configureStore.js và actions.js.