Cách tốt nhất để viết React Component

10778

Khi lần đầu tiên viết React, tôi đã tìm thấy nhiều cách khác nhau để viết component. Mặc dù framework đã phát triển đáng kể, nhưng dường như vẫn chưa đủ để thực hiện tốt công việc này.

Trong năm qua tại MuseFind, nhóm của chúng tôi đã viết rất nhiều các component React. Chúng tôi đã dần dần điều chính các cách tiếp cận khác nhau cho đến khi chúng tôi thực sự hài lòng với nó.

Hướng dẫn này trình bày các phương pháp hay nhất mà chúng tôi đã sử dụng. Chúng tôi hy vọng nó sẽ hữu ích, dù bạn là người mới bắt đầu hay là người có kinh nghiệm.

Một vài ghi chú, trước khi bắt đầu:

  • Chúng tôi sử dụng cú pháp của ES6 và ES7.
  • Nếu bạn không chắc chắn về sự phân biệt giữa component container hiện tại và container, chúng tôi khuyên bạn nên đọc phần này trước.
  • Vui lòng cho chúng tôi biết trong nhận xét nếu bạn có bất kỳ đề xuất, hoặc câu hỏi về React nào.

Class dựa trên các Component

Class dựa trên các component là state hoặc chứa các method. Chúng tôi sẽ cố gắng sử dụng chúng càng ít càng tốt, nhưng dù sao chúng cũng có chỗ đứng nhất định của chúng.

Hãy xây dựng component từng dòng một.

Nạp CSS

Về mặt lý thuyết thì tôi thích đặt CSS trong JavaScript. Nhưng nó vẫn là một ý tưởng mới. Trước khi ý tưởng đó hoàn thiện, chúng ta vẫn nhập một file CSS vào mỗi component.

Chúng tôi cũng tách dependency imports từ local imports bằng một dòng mới.

Khởi tạo State

Bạn cũng có thể sử dụng cách tiếp cận cũ hơn để khởi tạo state trong constructor. Thêm vào đó ở đây. Chúng tôi thích cách gọn gàng hơn.

Chúng tôi cũng đảm bảo export class mặc định.

propTypes và defaultProps

PropTypes và defaultProps là các thuộc tính tĩnh, được khai báo càng cao càng tốt trong component code. Chúng phải được hiển thị ngay cho các dev khác đọc file vì chúng được dùng làm tài liệu.

Nếu sử dụng React 15.3.0 hoặc cao hơn, hãy sử dụng gói prop-types thay vì React.PropTypes bởi cấu trúc độc đáo (dĩ nhiên).

Tất cả các component của bạn nên có propTypes.

Methods

Với các class component, khi bạn chuyển các method thành các tiểu hợp phần, bạn phải đảm bảo rằng chúng có quyền này khi chúng được gọi. Điều này thường đạt được bằng cách truyền this.handleSubmit.bind (this) vào tiểu hợp phần.

Chúng tôi nghĩ rằng cách tiếp cận này gọn và dễ dàng hơn mà vẫn giúp sửa chữa context tự động thông qua chức năng arrow của ES6.

Bỏ qua một hàm trong setState 

Trong ví dụ này, chúng tôi thực hiện việc này:

Đây là bí mật về setState, nó thực sự không đồng bộ. React thay đổi state vì các lý do hiệu suất, do đó state không thể thay đổi ngay sau khi setState được gọi.

Điều đó có nghĩa là bạn không nên dựa vào state hiện tại khi gọi setState – vì bạn không thể chắc chắn state  đó sẽ là gì!

Đây là giải pháp – bỏ qua một hàm trong setState, với state trước đó như là một đối số.

(Nhờ Austin Wood để được giúp đỡ trong phần này).

Destructuring các Props

Các component với nhiều props cần phải có mỗi bước trên một dòng mới, như ở trên.

Decorators

Nếu bạn đang sử dụng một cái gì đó như mobx, bạn có thể decorator các class component của bạn như vậy – tương tự như chuyển component vào một hàm.

Decorator là cách linh hoạt và có thể đọc được việc sửa đổi component chức năng. Chúng tôi sử dụng chúng rộng rãi, với mobx và thư viện các mô hình mobx của chúng ta.

Nếu bạn không muốn sử dụng decorator, hãy làm như sau:

Closures

Tránh chuyển closures mới thành các component con, như sau:

Đây là lý do tại sao: mỗi khi component gốc được hiển thị, một chức năng mới được tạo và truyền cho đầu vào.

Nếu đầu vào là một component React, điều này sẽ tự động kích hoạt nó để render lại, bất kể các props khác của nó đã thay đổi như thế nào.

Reconciliation là phần tốt nhất của React. Đừng khiến nó trở nên khó hơn mức cần thiết! Cộng thêm, bỏ qua class method khiến nó dễ đọc, debug và dễ thay đổi hơn.

Đây là component đầy đủ của chúng tôi:

Những Component hàm

Các component này không có state và không có method. Chúng là nguyên mẫu và dễ dàng để hiểu được. Sử dụng chúng càng thường xuyên càng tốt.

propTypes

Ở đây, chúng ta chỉ định các propTypes trước khai báo component, do đó chúng có thể nhìn thấy ngay lập tức. Chúng tôi có thể làm điều này vì chức năng hoist của JavaScript.

Destructure Props và defaultProps

Component của chúng ta là một chức năng, lấy các props của nó làm đối số của nó. Chúng ta có thể mở rộng chúng như sau:

Lưu ý rằng chúng tôi cũng có thể sử dụng đối số mặc định để hoạt động như defaultProp. Nếu mở rộng không xác định, chúng tôi sẽ đặt nó là false. (Trong một ví dụ bắt buộc, vì đó là một boolean, nhưng đó là cách tốt để tránh lỗi ‘Cannot read <property> of undefined’ với các đối tượng).

Tránh cú pháp ES6 sau:

Nhìn có vẻ rất hiện đại, nhưng chức năng ở đây thực sự không có tên.

Việc thiếu tên sẽ không là vấn đề nếu Babel của bạn được thiết lập đúng – nhưng nếu không, bất kỳ lỗi nào cũng có thể xuất hiện trong <<anonymous>> và đó là điều khủng khiếp khi debug.

Các chức năng không tên cũng có thể gây ra vấn đề với Jest, thư viện kiểm thử của Javascript. Do vấn đề khó khăn để hiểu lỗi (và sự thiếu lợi ích thực sự), chúng tôi khuyên bạn nên sử dụng function thay vì const.

Wrapping

Vì bạn không thể sử dụng decorator với các component chức năng, bạn chỉ cần bỏ qua nó như một đối số:

Đây là component đầy đủ của chúng tôi:

Điều kiện trong JSX

Rất có thể bạn đang thực hiện rất nhiều việc render có điều kiện. Dưới đây là những gì bạn muốn tránh khỏi:

Tuy nhiên, đặt chúng lồng vào nhau không phải là một ý tưởng hay.

Có một số thư viện giải quyết vấn đề này (JSX-Control Statements), nhưng thay vì giới thiệu một dependency khác, chúng tôi giải quyết theo cách tiếp cận này cho các điều kiện phức tạp:

Sử dụng dấu ngoặc nhọn đóng gói một IIFE và sau đó đưa câu lệnh if của bạn vào bên trong, trả về bất cứ điều gì bạn muốn render. Lưu ý rằng IIFE như thế này có thể gặp tác dụng phụ, nhưng trong nhiều trường hợp nó sẽ không đủ sức ảnh hưởng làm mất đi các factor dễ hiểu.

Cập nhật: Nhiều người bình luận đã đề xuất trích ra logic này cho một subcomponent có điều kiện trả về các nút khác nhau dựa trên props. Họ đang phải chia tách các component càng nhiều càng tốt và đó luôn luôn là lệnh call tốt. Nhưng hãy giữ lại phương pháp tiếp cận IIFE như là một biện pháp dự phòng cho các điều kiện nhanh.

Ngoài ra, khi bạn chỉ muốn render một phần tử trên một điều kiện, thay vì làm điều này …

… sử dụng short-circuit evaluation:

Cảm ơn các bạn đã theo dõi

Techtalk via Musefind