Composition React là gì

Bài viết được sự cho phép của tác giả Lưu Bình An

Composition một cách trừu tượng mà nói là việc đưa hai (hoặc nhiều) thứ khác nhau vào một chỗ để nhận được một loại kết quả 5 sai lầm thường thấy khi viết react component 7 lí do để loại bỏ Functional Components của React

Composition trong toán học

Toán học cũng chưa thật sự liên quan nhiều đến frontend, tuy nhiên toán học là nơi đã phát sinh ra khái niệm này

Ví dụ có 2 hàm, một hàm lày = 2 * x, hàm thứ 2 lày = x + 10.

Composition2 hàm này lại, kết quả của thằng này là input của thằng kia, chúng ta sẽ có hàm mớiy = (2 * x) + 10.Đó là tất cả khái niệm cần nắm

Function composition

Trong ngữ cảnh của functional programming, cũng không khác toán học, chỉ là được diễn tả bằng codelet date = getDate();let text = formatDate(date);let label = createLabel(text);showLabel(label);

Code này có vài đoạnna nánhau, chúng ta có nhận lấy một input, convert nó sang một loại khác, rồi lại lấy kết quả đó, convert tiếp.

Làm sao để lượt bỏ hết sựna náđó?let steps = [    getDate,    formatDate,    createLabel,    showLabel ]

Một vài người cho rằng code vậy sạch hơn. Viết một helper function để tin gọn hơn nữafunction runSteps(steps) {  let result;  for (let i = 0; i < steps.length; i++) {    let step = steps[i];    // làm tiếp các bước được móc nối vào    result = step(result);  }  return result;}

Nhờ sự trợ giúp của hàmrunStepschúng ta có thể viết lạirunSteps([    getDate,    formatDate,    createLabel,    showLabel ])

Nếu tổng số code bước phải làm là cố định, chúng ta muốn chạy y chang như vậy trên nhiều chỗ khác nhau, chúng ta tiếp tục đưa nó vào một functionfunction showDateLabel() {  runSteps([    getDate,    formatDate,    createLabel,    showLabel ]);}// Giờ gọi ở bất kỳ đâushowDateLabel();showDateLabel();

Các bạn lập trình lại tiến một bước xa hơn, sao không rút gọn code hơn nữa bằng một hàm gọi làpipelet showDateLabel = pipe(  getDate,  formatDate,  createLabel,  showLabel );// Giờ gọi ở bất kỳ đâushowDateLabel();showDateLabel();

Chúng tadấu diếmphần implement của thể đó như thế nàyfunction pipe(...steps) {  // chạy hết tất cả các function cho tui  return function runSteps() {    let result;    for (let i = 0; i < steps.length; i++) {      let step = steps[i];      result = step(result);    }    return result;  }}

Như vậy chúng ta đã đi rất xa, rất rất xa. Từ điểm xuất phát phải gọi lần lượt các hàm một cách thủ công, chúng ta chỉ định các bước cần chạy theo thứ tự một cáchsạch sẽ hơn// code cũlet date = getDate();let text = formatDate(date);let label = createLabel(text);showLabel(label); // code mớilet showDateLabel = pipe(  getDate,  formatDate,  createLabel,  showLabel );showDateLabel();

Nếu có thắc mắc trong đầu: ủa vậy để mần chi? Phức tạp rườm rà vãi cả ra! Hãy cân nhắc xem giữa hay cách viết trên, cách nào bạn đọc dễ hơn?

Khi hiểu đượcpipevà function composition bạn sẽ thấy mọi thứ gọn gàng rành mạch thật tuyệt vời, nhưng không có nghĩa là không có nhược điểm,outsourcechopipe, chúng ta không còn thấy được rõ ràng dữ liệu đã đi ra-đi vào như thế nào.

Component Composition

Một ngữ cảnh khác chúng ta cũng thấy sự xuất hiện của composition là lập trình UI hướng declarative. React component là một ví dụ.function App() {  return ;}function Screen() {  return

;}function Form() {  return ;}

Đấy cũng gọi là composition vì chúng ta đứa những component vào trong những component khác, rồi nhận được kết quả là một tổng thể chứa tất cả component

Một dạng biến thể của composition trong component làslot(làm Vue bạn sẽ biết khái niệm này)function Layout({ sidebar, content }) {  return (    

     
{sidebar}
     
{content}
   
 )}

Sau đấy đưa các giá trị cụ thể vào slotfunction HomePage() {  return (    }      content={}    >  ) } function AboutPage() {  return (    }      content={}    >  ) }

React sẽ không đặt hẳn một khái niệm riêng cho slot vì bạn có thể làm điều đó thông quaprop

Composition vs inheritance

Người đờithường đem composition để đối chiếu với inheritance, kế thừa gặp nhiều trong class và object hơn, composition gặp nhiều trong function

Một cách cụ thể, nếu viết code theo kiểuclass, bạn sẽ có xu hướng dùng lại các behavior từ một class khác bằng cáchextendnó (kế thừa). Tuy nhiên, làm vậy cũng có hạn chế là rất khó tùy chỉnh các behavior sau này. Ví dụ như tình huống muốnextendkhông chỉ một mà nhiềuclass

Đôi khi,miệng đờicũng đồn đại rằng việc dùng class khiến bạn bị khóa cứng trong thiết kế ban đầu vì việc thay đổi kiến trúc của các class thì rất chi là tốn công. Với việc dùng composition, thay vì extend, bạn dữ nguyên hiện trạng của một instance, sử dụng trực tiếp từ instance này và cũng có thể làm gì đó kết hợp với nhiều thứ khác, có nhiều đất diễn hơn.

Nói chung, ngành phần mềm đã bỏ việc model các UI component như một dạng kế thừa nhiều tầng nhiều cấp.

Không có nói inheritance lúc nào cũng tệ, nó chỉ không đủ bén như dao lam, sử dụng cần phải tiết chế, việc kế thừa đa cấp ở một độ sâu nhất định, đòi hỏi bạn đủ kiên nhẫn để giải quyết các vấn đề của nó.

If you write your code in a style that composes functions in some way before calling them, and there are other humans on your team, make sure that youre getting concrete benefits from this approach. It is not cleaner or better, and there is a price to pay for beautiful but indirect code.

Tạm kết: Nếu bạn làm việc trong team, hãy đảm bảo mọi người nhất trí với nhau lợi ích mà nó mang lại từ cách làm này. Nó không liên quan gì tới việc cleaner-better, nó luôn có cái giá phải trả cho beautiful nhưng mà code không trực quan.

Bài viết gốc được đăng tải tại vuilaptrinh.com

Có thể bạn quan tâm:

  • Những nguyên tắc chung mà Vue 3 đã áp dụng khi thiết kế
  • FPT.AI và công nghệ đứng sau do chính chủ nhân chia sẻ
  • 6 giải pháp tuyển dụng IT giúp thiết lập chiến lược chinh phục ứng viên tài năng

Xem thêm cácviệc làm Developerhấp dẫn tạiTopDev

Video liên quan