Ở bài viết trước chúng ta đã biết được Redux middleware là gì, và vấn đề gặp phải với lỗi: “Error: Actions must be plain objects. Use custom middleware for async actions” khi chúng ta cần xử lý các action bất đồng bộ như lấy dữ liệu từ API. Link bài viết trước mọi người có thể tham khảo ở đây

Trước hết phải thống nhất với nhau vị trí bạn nên xử lý các hành động bất đồng bộ (Asynchronous actions) trong Redux. Nếu như bên React chúng ta có thể gọi chúng trong useEffect (hoặc componentDidMount với class component) thì với Redux chúng ta nên đặt trong action creator. Tại sao? Cùng nhìn lại Redux Cycle nhé:

Rõ ràng không thể viết các xử lý bất đồng bộ vào trong action được vì nó là 1 plain object; cũng không nên viết vào Reducers vì reducers theo như kiến trúc redux thì chỉ là những functions nhận giá trị đầu vào là state hiện tại và 1 action để trả về 1 state mới: (state, action) => newState.

Để giải quyết lỗi “Error: Actions must be plain objects. Use custom middleware for async actions” chúng ta có Redux-thunk, một middleware dành riêng cho việc xử lý các action bất đồng bộ trong redux.

https://www.npmjs.com/package/redux-thunk

npm i redux-thunk --save-dev

Redux-thunk giúp trì hoãn việc phải dispatch 1 action cho đến khi bạn call APIs xong và trả về kết quả.

Để sử dụng được thunk, bạn cần phải nạp middleware này vào redux store của bạn trước.

import { createStore, applyMiddleware, compose } from "redux";
import rootReducer from "../reducers/index";
import { forbiddenWordsMiddleware } from "../middleware";
import thunk from "redux-thunk";

const storeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

const store = createStore(
  rootReducer,
  storeEnhancers(applyMiddleware(forbiddenWordsMiddleware, thunk))
);

export default store;

Lúc đó hàm getData sẽ thực hiện việc fetch dữ liệu các từ khóa bị cấm từ API, sau khi nhận được response trả về thì sẽ thực hiện dispatch action DATA_LOADED:

export function getData() {
  return function(dispatch) {
    return fetch("https://jsonplaceholder.typicode.com/posts")
      .then(response => response.json())
      .then(json => {
        dispatch({ type: "DATA_LOADED", payload: json });
      });
  };
}

Đơn giản đúng không. Redux-thunk thực sự là 1 middleware nhẹ nhàng mà có sức mạnh to lớn cho việc hoàn thiện lifecycle của Redux.

Cảm ơn các bạn đã đọc. Link tham khảo:

https://www.valentinog.com/blog/redux/#react-redux-tutorial-what-is-a-redux-middleware