Redux Saga là một thư viện middleware cho Redux, giúp xử lý các tác vụ bất đồng bộ (async) trong ứng dụng React. Nó dựa trên mô hình Generator của JavaScript để xử lý các tác vụ liên quan đến side effects (hiệu ứng phụ) như gọi API, xử lý bất đồng bộ, và quản lý trạng thái ứng dụng.
Redux Saga hoạt động dựa trên cơ chế watcher
và worker
. watcher
theo dõi các action
và kích hoạt worker
để xử lý tác vụ bất đồng bộ tương ứng. Kết quả của worker được trả về qua Redux Saga để cập nhật trạng thái trong Redux.
Để hiểu hơn về Redux Saga, ta cần làm rõ các thuật ngữ sau:
Generator
là một loại hàm đặc biệt trong JavaScript, được ký hiệu bằng dấu *
. Generator cho phép tạm dừng và tiếp tục thực thi ở các điểm đánh dấu bên trong hàm. Sử dụng Generator, Redux Saga có thể tạo ra các hàm xử lý bất đồng bộ một cách đơn giản và dễ dàng đọc.Watcher
là một Generator function theo dõi các action và kích hoạt worker tương ứng để xử lý tác vụ bất đồng bộ. Watcher lắng nghe và theo dõi các action được gửi từ Redux, và khi có action phù hợp, nó sẽ kích hoạt worker để xử lý tác vụ.Worker
là một Generator function được kích hoạt bởi watcher để xử lý các tác vụ bất đồng bộ. Trong worker, chúng ta có thể thực hiện các tác vụ như gọi API, xử lý bất đồng bộ, và gửi các action để cập nhật trạng thái trong Redux.Effect
là một đối tượng JavaScript đại diện cho một tác vụ bất đồng bộ trong Redux Saga. Redux Saga cung cấp các effect như takeEvery
, takeLatest
, call
, put
, và nhiều hơn nữa để giúp xử lý các tác vụ bất đồng bộ một cách dễ dàng và kiểm soát được trình tự thực thi.
Dưới đây là một ví dụ đơn giản về cách sử dụng Redux Saga trong ứng dụng React:
Cài đặt Redux Saga:
npm install redux-saga
Tạo file sagas.js
để định nghĩa các watcher và worker:
// sagas.js
import { takeEvery, put, delay } from 'redux-saga/effects';
function* incrementAsync() {
yield delay(1000);
yield put({ type: 'INCREMENT' });
}
function* watchIncrement() {
yield takeEvery('INCREMENT_ASYNC', incrementAsync);
}
export default function* rootSaga() {
yield all([watchIncrement()]);
}
Tạo file store.js
để kết nối Redux Saga với Redux:
// store.js
import { createStore, applyMiddleware } from 'redux';
import createSagaMiddleware from 'redux-saga';
import rootReducer from './reducers';
import rootSaga from './sagas';
const sagaMiddleware = createSagaMiddleware();
const store = createStore(rootReducer, applyMiddleware(sagaMiddleware));
sagaMiddleware.run(rootSaga);
export default store;
Sử dụng Redux Saga trong ứng dụng React:
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
function App() {
const count = useSelector((state) => state.count);
const dispatch = useDispatch();
const incrementAsync = () => {
dispatch({ type: 'INCREMENT_ASYNC' });
};
return (
<div>
<h1>Counter: {count}</h1>
<button onClick={incrementAsync}>Increment Async</button>
</div>
);
}
export default App;
Trong ví dụ trên, chúng ta đã tạo một watcher watchIncrement
và một worker incrementAsync
. Khi người dùng nhấp vào nút “Increment Async”, action INCREMENT_ASYNC
sẽ được gửi tới Redux Saga để kích hoạt worker incrementAsync
. Worker này sẽ tạm dừng trong 1 giây (delay(1000)
) và sau đó gửi action INCREMENT
để cập nhật trạng thái trong Redux.