Nếu bạn đã quen với React và đang tìm hiểu về Redux, có lẽ bạn đang cảm thấy bối rối trước những khái niệm như dispatch, store, action creator,… Thậm chí, khi bạn vừa bắt đầu làm quen với Redux, bạn có thể nghe ai đó nhắc đến Redux Thunk, và mọi thứ càng trở nên phức tạp hơn. Bài viết này sẽ giúp bạn hiểu rõ về cách thức hoạt động của Redux Thunk một cách đơn giản và dễ hiểu nhất.
1. Ôn Lại Về Redux
Redux là một thư viện JavaScript giúp quản lý trạng thái (state) của ứng dụng. Dựa trên kiến trúc Flux của Facebook và ngôn ngữ Elm, Redux thường được sử dụng kết hợp với React để tạo nên một bộ đôi hoàn hảo.
Trong ứng dụng Redux, toàn bộ trạng thái của ứng dụng được lưu trữ trong một Store duy nhất. Khi muốn thay đổi một phần của State, bạn cần tạo một Action từ một Component, đóng vai trò là Action creator. Thông thường, một Action là một object (lưu ý điểm này!). Action luôn trả về một type và có thể có hoặc không có payload. Ví dụ, một Action đơn giản trả về một đối tượng song cho Reducer có thể trông như sau:
export const selectedSong = song => {
return {
type: "SONG_SELECTED",
payload: song
};
};
Action này sẽ được gửi đến tất cả các Reducer. Chỉ những Reducer quan tâm đến type của Action này mới xử lý và trả về một state mới, sau đó được đưa đến Component dưới dạng props. Vòng đời của Redux có thể được mô tả như sau:
2. Redux Thunk Là Gì?
Vậy Redux Thunk là gì và nó được áp dụng như thế nào? Hãy xem xét lại ví dụ về Action ở trên. Action này trả về một plain Javascript object (PJO), một định dạng hợp lệ để Reducer có thể tiếp nhận và xử lý. Tuy nhiên, trong nhiều trường hợp, Action cần trả về một function, hay còn gọi là Async Action. Đây là nơi Redux Thunk phát huy tác dụng. Ví dụ:
import dataUsers from '../api/datausers';
export const getUsers = async () => {
const response = await sentayho.com.vn('/users');
return {
type: 'GET_USERS',
payload: response
}
};
Nhiều người mới làm quen với JavaScript hoặc React có thể nhầm lẫn và cho rằng đoạn code trên cũng là một PJO. Tuy nhiên, việc sử dụng cú pháp ES6 có thể gây nhầm lẫn. Nếu bạn thử kiểm tra đoạn code trên với Babel, bạn sẽ thấy phần return trả về một đoạn code dài dòng, phức tạp, chứ không phải là một PJO đơn giản. Do đó, cách tiếp cận trên không phù hợp với khái niệm của một Action thông thường.
Redux Thunk cho phép các Action trả về một function thay vì chỉ là một PJO. Nó đóng vai trò là một Middleware, được đặt trước thời điểm reducer nhận request để nhận biết các action có trả về một PJO hay không.
- Nếu Action trả về là một PJO: Thunk sẽ chuyển action đó đến Reducer như bình thường.
- Nếu Action trả về là một function: Redux Thunk sẽ “chặn” action đó lại và đợi cho đến khi một lệnh asynchronous nào đó trong function hoàn tất và trả về kết quả (ví dụ như giá trị
responseở trên). Sau đó, nó sẽ tạo ra một PJO và chuyển action này đến Reducer như bình thường.
Sơ đồ sau minh họa quy trình này:
Để sử dụng Thunk, thay vì return, ta sử dụng hàm dispatch:
import dataUsers from '../api/datausers';
export const getUsers = () => async dispatch => {
const response = await sentayho.com.vn('/users');
dispatch({ type: 'GET_USERS', payload: response });
};
Trong đoạn code trên, dispatch là một hàm được cung cấp bởi Redux, cho phép bạn gửi một action đến store. Khi Redux Thunk thấy một action là một hàm, nó sẽ gọi hàm đó với dispatch làm đối số. Hàm đó sau đó có thể thực hiện các tác vụ bất đồng bộ, và khi hoàn thành, nó sẽ gọi dispatch để gửi một action thực tế đến store.
3. Kết Luận
- Redux Thunk là một Middleware cho phép bạn viết các Action trả về một function thay vì một plain javascript object bằng cách trì hoãn việc đưa action đến reducer.
- Redux Thunk được sử dụng để xử lý các logic bất đồng bộ phức tạp cần truy cập đến Store hoặc đơn giản là việc lấy dữ liệu như Ajax request.
Hy vọng bài viết này đã giúp bạn hiểu rõ hơn về Redux Thunk và cách nó được sử dụng trong các dự án thực tế. Trong các bài viết tiếp theo, chúng ta sẽ tìm hiểu sâu hơn về Async Action với Redux Thunk.
Tham khảo sentayho.com.vn/@User3141592/understanding-the-redux-thunk-source-code-b3f8b930faf6
