Khi nào nên sử dụng các thành phần React dựa trên lớp ES6 so với các thành phần React ES6 chức năng?


211

Sau khi dành thời gian tìm hiểu React, tôi hiểu sự khác biệt giữa hai mô hình chính của việc tạo các thành phần.

Câu hỏi của tôi là khi nào tôi nên sử dụng cái nào và tại sao? Lợi ích / sự đánh đổi của cái này so với cái kia là gì?


Các lớp ES6:

import React, { Component } from 'react';

export class MyComponent extends Component {
  render() {
    return (
      <div></div>
    );
  }
}

Chức năng:

const MyComponent = (props) => {
    return (
      <div></div>
    );
}

Tôi đang suy nghĩ chức năng bất cứ khi nào không có trạng thái bị thao túng bởi thành phần đó, nhưng có phải vậy không?

Tôi đoán nếu tôi sử dụng bất kỳ phương pháp vòng đời nào, tốt nhất nên đi với một thành phần dựa trên lớp.


7
Có vẻ như bạn đã biết câu trả lời.
Felix Kling

2
Nếu bạn chỉ có một thành phần với phương thức kết xuất, bạn có thể biến nó thành dạng chức năng. Nếu bạn cần một cái gì đó nhiều hơn chức năng kết xuất không trạng thái, hãy sử dụng các lớp
just-boris 20/03/2016

2
Để ngắn gọn hơn nữa, hãy thử điều này:const MyComponent = (props) => <div>...</div>
Viliam Simko

1
Tôi không bao giờ sử dụng chức năng nếu nó có thể tránh được. Bởi vì tôi chắc chắn cuối cùng cần phải cấu trúc lại lớp dựa trên đường. Và sau đó thường cần phải cấu trúc lại chức năng sau đó.
keithjgrant

Vào năm 2020, cách tiếp cận đúng là sử dụng các thành phần chức năng bất cứ khi nào có thể, bởi vì chúng hỗ trợ các móc và móc là (hiệu suất và kiến ​​trúc) tốt hơn so với các lựa chọn thay thế.
polkovnikov.ph

Câu trả lời:


161

Bạn có ý tưởng đúng. Đi với chức năng nếu thành phần của bạn không làm nhiều hơn là nhận một số đạo cụ và kết xuất. Bạn có thể coi đây là các hàm thuần túy bởi vì chúng sẽ luôn hiển thị và hoạt động giống nhau, được cung cấp cùng một đạo cụ. Ngoài ra, họ không quan tâm đến các phương pháp vòng đời hoặc có trạng thái nội bộ của riêng họ.

Vì chúng nhẹ, nên việc viết các thành phần đơn giản này là các thành phần chức năng là khá chuẩn.

Nếu các thành phần của bạn cần nhiều chức năng hơn, như giữ trạng thái, thay vào đó hãy sử dụng các lớp.

Thông tin thêm: https://facebook.github.io/react/docs/reUs-components.html#es6- classes


EDIT : Phần lớn những điều trên là đúng, cho đến khi giới thiệu React Hook.

  • componentDidUpdatecó thể được nhân rộng với useEffect(fn), đâu fnlà chức năng để chạy khi đăng ký lại.

  • componentDidMountcác phương thức có thể được sao chép với useEffect(fn, []), fnhàm chạy ở đâu khi đăng ký lại và []là một mảng các đối tượng mà thành phần sẽ chạy lại, nếu và chỉ khi có ít nhất một thay đổi giá trị kể từ lần kết xuất trước. Như không có, useEffect()chạy một lần, trên đỉnh đầu tiên.

  • statecó thể được sao chép với useState(), có giá trị trả về có thể bị hủy theo tham chiếu của trạng thái và hàm có thể đặt trạng thái (nghĩa là const [state, setState] = useState(initState)). Một ví dụ có thể giải thích điều này rõ ràng hơn:

const Counter = () => {
  const [count, setCount] = useState(0)

  const increment = () => { 
    setCount(count + 1);
  }

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>+</button>
    </div>
  )
}

default export Counter

Liên quan đến khuyến nghị khi nào nên sử dụng lớp trên các thành phần chức năng, Facebook chính thức khuyến nghị sử dụng các thành phần chức năng bất cứ khi nào có thể . Bên cạnh đó, tôi đã nghe một số người thảo luận về việc không sử dụng các thành phần chức năng vì lý do hiệu suất, cụ thể là

"Các chức năng xử lý sự kiện được xác định lại trên mỗi kết xuất trong các thành phần chức năng"

Mặc dù đúng, vui lòng xem xét nếu các thành phần của bạn thực sự hiển thị ở tốc độ hoặc âm lượng như vậy mà điều này sẽ đáng quan tâm.

Nếu có, bạn có thể ngăn xác định lại chức năng bằng cách sử dụng useCallbackuseMemomóc. Tuy nhiên, hãy nhớ rằng điều này có thể làm cho mã của bạn (kính hiển vi) kém hơn về hiệu suất .

Nhưng thành thật mà nói, tôi chưa bao giờ nghe nói về việc xác định lại các chức năng là một nút cổ chai trong các ứng dụng React. Tối ưu hóa sớm là gốc rễ của mọi tội lỗi - lo lắng về điều này khi nó là một vấn đề


Điều gì về chức năng không giữ trạng thái, nhưng được kết hợp chặt chẽ với thành phần, ví dụ: xác định một số thuộc tính động cho kết xuất.
Dennis

Đây là bài viết hay nhất về sự khác biệt giữa hai loại thành phần trong React: code.tutsplus.com/tutorials/ Kẻ
Arian Acosta

5
Kể từ React 16.8, bạn có thể sử dụng trạng thái trong một thành phần chức năng, thông qua useStatehook.
Greg

Kể từ React 16.8, bạn có thể thực hiện hầu hết mọi thứ trong các thành phần chức năng và tất cả các hiệu ứng cuối cùng có thể được mô đun hóa chỉ với một tác động tối thiểu đến hiệu suất.
polkovnikov.ph

1
Bạn đã tìm thấy thông tin ở đâu Facebook officially recommends using functional components wherever possible?
johannchopin

40

Luôn cố gắng sử dụng các chức năng không trạng thái (các thành phần chức năng) bất cứ khi nào có thể. Có những tình huống bạn sẽ cần sử dụng lớp React thông thường:

  • Thành phần cần duy trì trạng thái
  • Thành phần này được kết xuất lại quá nhiều và bạn cần kiểm soát thông qua đó shouldComponentUpdate
  • Bạn cần một thành phần container

CẬP NHẬT

Giờ đây đã có một lớp React được gọi là PureComponentbạn có thể mở rộng (thay vì Component), lớp này thực hiện lớp riêng shouldComponentUpdateđể chăm sóc so sánh các đạo cụ nông cho bạn. Đọc thêm


43
Always try to use stateless functions (functional components) whenever possible.Tôi đã đọc mười người nói rằng. Vẫn không ai trong số họ đưa ra một lời giải thích tại sao.
Rotareti

25
In an ideal world, most of your components would be stateless functions because in the future we’ll also be able to make performance optimizations specific to these components by avoiding unnecessary checks and memory allocations. This is the recommended pattern, when possible.Thông tin thêm: facebook.github.io/react/docs/ Từ
Diogo Cardoso

2
@rotareti Tôi không biết nếu bạn cảm thấy bạn đã trả lời câu hỏi của mình, nhưng các hàm thuần túy sẽ đơn giản hơn nhiều để hiểu, kiểm tra và duy trì. Cho cùng một tham số, chúng luôn luôn hiển thị cùng một thứ. Các thành phần duy trì trạng thái và thay đổi khi các sự kiện vòng đời xảy ra là khó hiểu hơn. Không phải nói rằng đôi khi chúng không cần thiết, nhưng tôi hy vọng rõ ràng rằng nếu không cần lợi thế của chúng, tất cả những gì chúng làm là thêm các bản tóm tắt không mong muốn và chi phí không có lợi ích.
door_number_three

Bạn cũng sẽ muốn tạo một lớp Thành phần nếu bạn có các định nghĩa xử lý sự kiện của riêng bạn. Bằng cách đó, bạn có thể liên kết trước các trình xử lý sự kiện đó với thành phần trong hàm tạo thay vì tạo một hàm mới trên mỗi kết xuất. Lưu ý điều này là không cần thiết nếu tất cả các trình xử lý sự kiện của bạn đến từ các đạo cụ.
Dobes Vandermeer

Lưu ý rằng đề xuất Facebook được trích dẫn không còn tồn tại (xem bình luận của tôi ở trên).
Garrett

34

CẬP NHẬT tháng 3 năm 2019

https://overreacted.io/how-are-feft-components-different-from-groupes/

CẬP NHẬT tháng 2 năm 2019:

Với việc giới thiệu các móc React , dường như các nhóm React muốn chúng tôi sử dụng các thành phần chức năng bất cứ khi nào có thể (điều này tốt hơn theo bản chất chức năng của JavaScript).

Động lực của họ:

1.) Its hard to reuse stateful logic between components
2.) Complex components become hard to understand
3.) Classes confuse both people and machines

Một thành phần chức năng với các móc có thể làm hầu hết mọi thứ mà một thành phần lớp có thể làm, mà không có bất kỳ đề cập nào ở trên.

Tôi khuyên bạn nên sử dụng chúng ngay khi bạn có thể.

Câu trả lời gốc

Các thành phần chức năng không nhẹ hơn các thành phần dựa trên lớp, "chúng thực hiện chính xác như các lớp." - https://github.com/facebook/react/issues/5677#issuecomment-241190513

Liên kết trên có một ít ngày, nhưng tài liệu của React 16.7.0 nói rằng các thành phần chức năng và lớp:

"tương đương với quan điểm của React." - https://reactjs.org/docs/components-and-props.html#statless-fifts

Về cơ bản không có sự khác biệt giữa một thành phần chức năng và một thành phần lớp chỉ thực hiện phương thức kết xuất, ngoại trừ cú pháp.

Trong tương lai (trích dẫn liên kết ở trên) "chúng tôi [Phản ứng] có thể thêm các tối ưu hóa như vậy."

Nếu bạn đang cố gắng tăng hiệu suất bằng cách loại bỏ các kết xuất không cần thiết, cả hai phương pháp đều cung cấp hỗ trợ. memocho các thành phần chức năng và PureComponentcho các lớp.

- https://reactjs.org/docs/react-api.html#reactmemo

- https://reactjs.org/docs/react-api.html#reactpurecomponent

Nó thực sự tùy thuộc vào bạn. Nếu bạn muốn ít nồi hơi hơn, hãy đi chức năng. Nếu bạn yêu thích lập trình chức năng và không thích các lớp học, hãy sử dụng chức năng. Nếu bạn muốn có sự thống nhất giữa tất cả các thành phần trong cơ sở mã của bạn, hãy đi với các lớp. Nếu bạn cảm thấy mệt mỏi với việc tái cấu trúc từ các thành phần dựa trên chức năng sang lớp khi bạn cần một cái gì đó như thế state, hãy đi với các lớp.


1
Tôi nghĩ rằng làm cho mọi thành phần mở rộng React.Component làm cho mã dễ đọc hơn, đặc biệt là đối với những người mới. Thật tuyệt khi bạn thấy một thành phần được tạo ra theo cùng một cách mỗi lần. Giống như @Galupuf đã nói, các thành phần đơn giản chỉ có một phương thức gọi là "render ()". Thật tuyệt khi làm mọi thứ mở rộng React.Component bởi vì khi bạn muốn bắt đầu ràng buộc "cái này", có trạng thái, v.v. bạn không phải cấu trúc lại mọi thứ, bạn chỉ cần thêm những gì bạn cần.
jeffski13

10

Kể từ React 16.8, thuật ngữ Các thành phần chức năng không trạng thái là sai lệch và nên tránh vì chúng không còn trạng thái nữa ( React.SFC không dùng nữa , Dan Abramov trên React.SFC ), chúng có thể có trạng thái, chúng có thể có móc (hoạt động như Các phương thức vòng đời) cũng vậy, chúng ít nhiều trùng lặp với các thành phần lớp

Các thành phần dựa trên lớp

Thành phần chức năng:

Tại sao tôi thích các thành phần Funtional

  • Phản ứng cung cấp móc useEffect mà là một cách rất rõ ràng và súc tích để kết hợp componentDidMount, componentDidUpdatecomponentWillUnmountphương pháp vòng đời
  • Với các hook bạn có thể trích xuất logic có thể dễ dàng chia sẻ giữa các thành phần và có thể kiểm tra
  • ít nhầm lẫn về phạm vi

Phản ứng động lực tại sao sử dụng móc (tức là các thành phần chức năng).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.