Redux Thunk vs Redux Saga

1. Mở đầu

  • Đến bây giờ bạn đã hoàn thành một số hướng dẫn Redux và cảm thấy như bạn đã sẵn sàng để bắt tay vào một project

  • Sau một số máu, mồ hôi và nước mắt, bạn đã xây dựng một bộ giảm tốc và một số hành động. Bạn đang tiến bộ! Mọi thứ đang bắt đầu nhấp và bạn cảm thấy như cuối cùng bạn đã thành công!

  • Nhưng rồi ... Bùm! Bạn đập vào tường vì bạn nhận ra rằng bạn chưa thể hiển thị component vì bạn không có bất kỳ dữ liệu nào cho nó !!!

    • Bạn: Vâng, được rồi, Redux, làm cách nào để tải dữ liệu?
    • Redux: Đừng quan tâm.
    • Bạn: Có gì để thêm không, React?
    • Phản ứng: Không phải vấn đề của tôi.
  • Vì vậy, bạn đọc thêm một số blog khác, đánh vào một số tài nguyên cộng đồng, nhưng kết thúc với nhiều câu hỏi hơn là câu trả lời. Theo như bạn có thể nói, một nửa cộng đồng sử dụng thunks và nửa còn lại sử dụng sagas. Chà, ai đúng?

2. Thunk với Saga

  • Về mặt triển khai, Redux-Thunk và Redux-Saga không có khác biệt lớn. Tuy nhiên, xét về những gì bạn có thể làm với nó, thì thực sự rất giống nhau nhưng lại cũng chẳng giống nhau. Redux-Thunk và Redux-Saga khác nhau theo một vài thứ.
  • Nhưng trước khi nói về điều này thì ta sẽ nói về redux thunk và redux saga là gì. Nó đều là các thư viện trung gian cho redux. Redux middleware là mã chặn các hành động đi vào store thông qua phương thức dispatch()
  • Một action có thể làm bất cứ điều gì (theo nghĩa đen)
  • Nhưng nếu bạn đang theo dõi thực hành tốt nhất thì một hành động là một đối tượng javascript đơn giản với một trường type, tùy chọn payload, meta và các trường error. Ví dụ:
    const loginRequest = {
   type: 'LOGIN_REQUEST',
   payload: {
       name: 'admin',
       password: '123',
   },
};

(nhân tiện, cấu trúc này được gọi là Flux Standard Action)

  • Đây là những gì type signature trông giống như trong TypeScript
type Action = {
    type: string;
    payload?: any;
    meta?: any;
    error?: boolean;
};

3. Redux-Thunk

  • Ngoài việc gửi các hành động tiêu chuẩn, phần mềm trung gian Redux-Thunk cho phép bạn gửi các chức năng đặc biệt, được gọi là thunks
  • Thunks (trong Redux) thường có cấu trúc sau:
export const thunkName =
   parameters =>
        (dispatch, getState) => {
            // Your application logic goes here
        };

Nghĩa là, thunk là một hàm (tùy chọn) nhận một số tham số và trả về một hàm khác. Hàm bên trong có một hàm dispatch và một hàm getState - cả hai sẽ được cung cấp bởi Redux-Thunk middleware

  • Ở đây chúng ta có một ví dụ: thunk cố gắng gọi API đăng nhập bằng tên người dùng và mật khẩu. Thunk đầu tiên gửi một hành động chỉ ra rằng yêu cầu đang bắt đầu. Sau đó, nó thực hiện cuộc gọi. Cuối cùng, nó gửi một hành động thành công hoặc một hành động thất bại tùy thuộc vào việc cuộc gọi API có thành công hay không
import * as api from 'api';
import { loginRequest, loginSuccess, loginFailure } from './loginActions';
export const loginThunk =
    (name: string, password: string) =>
        (dispatch: Function) => {
            dispatch(loginRequest());
            try {
                api.login(name, password);
            }
            catch (err) {
                dispatch(loginFailure(err));
            }
            dispatch(loginSuccess());
        };

Khi bạn gửi thunk của mình, ví dụ dispatch(loginThunk('admin', 'secret')); Redux-Thunk gọi chức năng bên trong của bạn, về cơ bản là:

(dispatch: Function) => {
    dispatch(loginRequest());
    try {
        api.login('admin', 'secret'); // values from closure
    }
    catch (err) {
        dispatch(loginFailure(err));
    }
    dispatch(loginSuccess());
};

4. Redux-Saga

Chúng ta đã trình bày những điều cơ bản về Redux-thunk, hãy xem Redux-Saga

  • Redux-Saga middleware cho phép bạn thể hiện logic ứng dụng phức tạp dưới dạng các hàm thuần túy được gọi là sagas. Các chức năng thuần túy được mong muốn từ quan điểm kiểm tra vì chúng có thể dự đoán và có thể lặp lại, điều này làm cho chúng tương đối dễ kiểm tra.
  • Sagas được thực hiện thông qua các chức năng đặc biệt gọi là chức năng tạo (generator functions). Đây là một tính năng mới của ES6 JavaScript. Về cơ bản, thực thi nhảy vào và ra khỏi một trình tạo ở mọi nơi bạn thấy một yield câu lệnh. Hãy nghĩ về một yield statement là làm cho trình tạo tạm dừng và trả về giá trị mang lại. Sau đó, người gọi có thể tiếp tục trình tạo tại câu lệnh sau yield.
  • Một hàm tạo là một định nghĩa như thế này. Lưu ý dấu hoa thị sau từ khóa chức năng
function* mySaga() {
    // ...
}

Chúng ta có thể viết lại chức năng đăng nhập từ trước như một saga. Nó trông như thế này:

import * as api from 'api';
import { LoginRequestAction, loginSuccess, loginFailure } from './loginActions';
function* loginSaga() {
    const action: LoginRequestAction = yield take('LOGIN_REQUEST');
    const { name, password } = action.payload;
    try {
        yield call(api.login, name, password);
    }
    catch (err) {
        yield put(loginFailure(err));
        return;
    }
    yield put(loginSuccess());
}

Khi saga đăng nhập được đăng ký với Redux-Saga, nó sẽ bắt đầu thực thi ngay lập tức. Nhưng sau đó, yield take dòng đầu tiên sẽ tạm dừng saga cho đến khi một hành động với loại 'LOGIN_REQUEST' được gửi đến store. Một khi điều đó xảy ra, thực thi sẽ tiếp tục.

5. Kết luận

  • Bạn có thể nghĩ rằng sự khác biệt lớn nhất là trong cú pháp. Mặc dù sự thật là viết và lý luận về thunks và sagas khá khác nhau, nhưng nó là một điều gì đó lớn hơn.
  • Thunks không bao giờ có thể hành động để đáp ứng với một hành động. Mặt khác, Redux-Saga đăng ký vào store và có thể kích hoạt một saga để chạy hoặc tiếp tục khi một hành động nhất định được gửi đi.
  • Mỗi cái đều có ưu và nhược riêng, tùy theo độ hiểu biêt của bạn về thunk và saga để có thể áp dụng vào các project của mình

6. Tham khảo

https://decembersoft.com/posts/redux-thunk-vs-redux-saga/