Loại bỏ mẫu Redux với Hook-for-redux

Tram Ho

Bài viết được dịch từ bài viết How I Eliminated Redux Boilerplate with Hooks-for-Redux

Redux rất là tuyệt vời. Nó giúp bạn quản lý, kiểm tra state của ứng dụng một cách dễ dàng nhất. Hơn nữa, có rất nhiều thư viện hỗ trợ để bạn nghịch redux như là: react-redux, redux-devtools, redux-logger.

Tuy nhiên Redux lại có một điểm trừ, đó là phải tốn quá nhiều thời gian để viết redux theo một mẫu tiêu chuẩn. Mà đáng ra điều này phải được làm tự động.

Sau khi tham gia một số dự án sử dụng Redux và nhận thấy các kiểu mẫu này, tôi bắt đầu thiết kế một công cụ để tự động hóa nó. Điều này đã được nhiều người nhận thấy trước đó rồi: reduce-react-boilerplate, reducing-boilerplate-in-redux, minimize-redux-boilerplate-in-4-lines-of-code, cũng như là giải quyết vấn đề này: reduxless, redux-actions, redux-archơn thế nữa. Tuy nhiên những cách trước đó đều thất bại vì một trong hai lý do sau:

  1. Tạo ra một giải pháp không tích hợp được hệ thống Redux.
  2. Không loại bỏ được sự dư thừa của mẫu tiêu chuẩn Redux.

Vậy là tôi đã tạo ra hooks-for-redux. Tôi thích cái cách mà Hooks làm cho React gọn gàng hơn, nên tôi đã tạo ra một Api tương tự để làm gọn Redux. Sau đây là ví dụ về cách mà H4R hoạt động:

Cách tôi dùng H4R để loại bỏ 52% mã trong ứng dụng React-Hook-Todo

Gần đây tôi có đọc được một bài viết tuyệt vời của Sunil Sandhu, kể chi tiết cách Hooks làm gọn Redux trong Components. Tôi sẽ dùng kết quả của anh ấy làm khởi đầu:

Cho những ai lười, bạn có thể thấy được kết quả ở đây:

Logic cơ bản của ứng dụng To-Do

Trước khi đi vào code, sẽ tốt hơn nếu hiểu được logic của ứng dụng. Bắt đầu với giao diện người dùng, chúng ta sẽ có một mã giả cho React component như thế này:

Như bạn thấy, chỉ có hai thành phần. ToDo bao gồm:

  • Một danh sách các ToDoItem lấy từ useList. Mỗi Item chứa:
    • Văn bản hiển thị.
    • Một nút để xóa phần tử.
  • Một input để thêm một ToDo mới

Mã giả này gần như có đủ chức năng, ngoại trừ hàm addItem và hàm deleteItem được truyền vào như tham số

Phần còn lại của ứng dụng là quản lý danh sách việc cần làm.

Ở phần đầu, chúng ta có cấu trúc của danh sách, và state khởi tạo ban đầu.

Tiếp theo là mô tả 2 chức năng: thêm và xóa phần tử. Lấy danh sách hiện tại, thực hiện thêm và trả về một danh sách mới.

Cuối cùng có ba mô tả sơ khai cho các chức năng trên:

  • useList trả về giá trị danh sách hiện tại.
  • deleteItem xóa phần tử khỏi danh sách
  • addItem thêm phần tử vào danh sách

Toàn bộ logic cần thiết của ứng dụng ToDo chỉ tốn khoảng 30 dòng code. Một ứng dụng thực tế sẽ tốn nhiều hơn, nhưng mục tiêu ở đây là càng ít càng tốt.

Bắt đầu nào

Bắt đầu với file gốc index.js. Tôi sẽ cho bạn thấy trước và sau và giải thích sự thay đổi.

Tôi sử dụng số dòng để đo kích thước code. Mặc dù nó không phải là phương pháp tốt, nhưng nó đơn giản. Thêm về suy nghĩ về việc đếm code trong tokens

src/index.js (22% gọn hơn)

Ban đầu

Sau đó

Bạn sẽ nhận thấy được 2 thay đổi ở đây. Đầu tiên không có lệnh gọi configureStore và thứ hai là Provider không yêu cầu tham số store. Hook-for-redux được thiết kế để thêm các reducer vào đang tồn tại thay vì yêu cầu tất cả các reducer khi khởi tạo store. Điều này cho phép chúng ta sử dụng store mặc định. Bạn vẫn có thể ghi đè store mặc định nếu cần.

src/App.js (67% gọn hơn)

Ban đầu

Sau đó

Đơn giản hóa App.js khá đơn giản. App.js không nên phụ thuộc và trạng thái danh sách. Điều này sẽ gây nên một số vấn đề về việc re-render.

src/components/ToDo.js (42% gọn hơn)

ToDo là thành phần chính trình bày todo-list. Đây là file lớn và có nhiều thay đổi nhất. Đa phần là cải tiến nhỏ trong cách sử dụng React. Mục tiêu là giảm mã mà không mất đi sự rành mạch.

Ban đầu:

Sau đó

Làm gọn mã React:

  • Tôi sử dụng export-const thay vì export-default. Một số vấn đề với export-default là khi nhập mặc định, bạn có thể gán bất cứ tên nào bạn muốn và điều đó tạo nên sự không nhất quán trong dự án. Tuy nhiên vấn đề lớn nhất của export-default là nó không hoạt động với import * hay export * – đây là một cấu trúc tốt để giảm mã.
  • Giảm bớt định nghĩa hàm cho những hành động chỉ sử dụng một lần.

Và những thay đổ đáng kể nữa:

  • Import trực tiếp addItemuseList. Chúng không nên được truyền vào như là một props
  • Loại bỏ generateId. Đây không phải là trách nhiệm của component ToDo.
  • Loại bỏ deleteItem. ToDo.js không bao giờ sử dụng chúng.

src/components/ToDoItem.js (35% gọn hơn)

Ban đầu

Sau đó

  • deleteItem import trực tiếp thay vì nhận từ props
  • export-const giống với ToDo.js
  • phân mảnh props và return trực tiếp

redux/list.js (74% dòng rút gọn, 80% file rút gọn)

Bây giờ mới là ma thuật thật sự. H4R useRedux loại bỏ tất cả bản mẫu để quản lý redux store của bạn, và nó không làm mất đi tính tương thích ban đầu. Đặt tất cả redux logic vào trong 1 file.

Lưu ý, trong dự án lớn hơn, tôi khuyên bạn nên tạo một tệp cho mỗi model dữ liệu. Tuy nhiên, trong ứng dụng đơn giản này, chỉ cần có duy nhất một model: danh sách todo.

Ban đầu (5 file – 61 dòng)

Sau đó (1 file – 16 dòng)

getUniqueId cơ bản giống như generatedId ban đầu ở ToDo.js. Phần còn lại là lệnh gọi useRedux. Gồm có 3 đối số:

  1. storeKey tên của state được lưu trong redux store
  2. state khởi tạo
  3. reducer

Và nó có trả về:

  1. Một hook để lấy state hiện tại và re-render lại mỗi khi state thay đổi
  2. Một đối tượng chứa các dispatchers tương ứng với reducer

Đây là cách hooks-for-redux thực thi. Nó lấy thông tin cần thiết để định nghĩa state của bạn – tên, state khởi tạo và reducer và nó trả về các phương thức cần thiết để tương tác với state đó.

Cuối cùng! Chúng ta đã làm như thế nào?

Mã nguồn ban đầu là 177 dòng code. Với hooks-for-redux, nó được tối giản xuoons còn 85 dòng. Chỉ 48% số dòng và từ 9 file xuống còn 5. Bạn có thể hợp nhất tất cả vào cùng một file, và loại bỏ được các dòng importexport và nếu loại bỏ cả style thì nó có thể giảm xuống còn 45 dòng.

Chia sẻ bài viết ngay

Nguồn bài viết : Viblo