- vừa được xem lúc

Bạn đã biết về Container/Presentational với React?

0 0 19

Người đăng: Nguyễn Tích Duy

Theo Viblo Asia

Bài viết này tham khảo từ tác giả Dan_abramov (tác giả của Redux). Mục đích bài viết là mong sẽ đem lại một góc nhìn về một design pattern khá là hay khi xây dựng code base với react, vue,... Cũng như là mở ra một series bài viết về design pattern cho phía front-end.

Nguyên lí

Container/Presentational là một design pattern nhằm thực thi tách các mối quan tâm (separation of concerns) bằng cách tách các phần hiển thị khỏi logic ứng dụng.

Bài toán đơn giản là chúng ta cần tạo một ứng dụng tải 6 ảnh từ server và hiển thị các ảnh đó lên màn hình:

Ý tưởng khi áp dụng với react là chia làm 2 loại components:

  1. Presentational Components: Là những components chịu trách nhiệm cho việc những gì xuất hiện trên màn hình mà người dùng có thể thấy được. Ví dụ ở đây là danh sách hình ảnh những chú chó.
  2. Container Components: Là những components chịu trách nhiệm cho việc xử lí dữ liệu. Ví dụ ở đây là Xử lí tải về hình ảnh từ server.

Presentational Component

Một số các chức năng chính của các presentational component là:

  • Chịu trách nhiệm về mọi thứ sẽ hiển thị trông như thế nào (html, css).
  • Nhận các dữ liệu và callback thông qua prop.
  • Không chỉ định cách dữ liệu tải hoặc chỉnh sửa như thế nào.
  • Thường là stateless component (không có các state bên trong nó) trừ khi cần state với mục đích xử lí các phần giao diện.
  • Không chứa các phần phụ thuộc khác trong ứng dụng, ví dụ: redux

Ở ví dụ dưới đây chúng ta có một presentational component là DogList nhận dữ liệu thông qua prop là dogs và hiển thị ra danh sách ảnh của những chú chó.

const DogList = ({ dogs }) => { return dogs?.map((dog, i) => ( <div style={{ width: "70%", margin: "auto" }} key={i}> <img src={dog} alt="dogs" width="100%" /> </div> ));
};
export default DogList;

Ví dụ 1

Container Component

Một số các chức năng chính của các container component là:

  • Chịu trách nhiệm về mọi thứ sẽ hoạt động như thế nào.
  • Cung cấp dữ liệuhành vi cho presentational hoặc các container components khác.
  • Truyền các Flux/Redux actions hoặc các lệnh gọi api dưới dạng các callback cho presentational components.
  • Thường là stateful, là nguồn chứa dữ liệu.

Tiếp nối với ví dụ 1, dưới đây chúng ta có DogListContainer component với nhiệm vụ là gọi lấy dữ liệu từ API bên ngoài và truyền xuống DogList component thông qua dogs props.

import { useEffect, useState } from "react";
import DogList from "./DogList"; const DogListContainer = () => { const [dogs, setDogs] = useState(); useEffect(() => { fetch("https://dog.ceo/api/breed/labrador/images/random/6") .then((value) => value.json()) .then((value) => setDogs(value.message)); }, []); return <DogList dogs={dogs} />;
}; export default DogListContainer;

Ví dụ 2

Hook

Với sự ra đời của Hooks giúp dễ dàng cho các nhà phát triển cô lậptái sử dụng các logic khiến cho tác dụng của container component ngày càng giảm đi. Việc áp dụng hook giúp cải thiện sự kết hợp (composition) hơn vì sử dụng nhiều hooks trong cùng một component sẽ đơn giản hơn việc chuyển các prop từ nhiều container component tời cùng một components.

Từ ví dụ 2 chúng ta tách logic thành hook useDogList với nhiệm vụ gọi api lấy dữ liệu và trả dữ liệu về là dogs.

import { useEffect, useState } from "react"; const useDogList = () => { const [dogs, setDogs] = useState(); useEffect(() => { fetch("https://dog.ceo/api/breed/labrador/images/random/6") .then((value) => value.json()) .then((value) => setDogs(value.message)); }, []); return { dogs };
};
export default useDogList;

DogListHook.js

Chúng ta chuyển DogListContainer.js thành như sau:

import DogList from "./DogList";
import useDogList from "./DogListHook"; const DogListContainer = () => { const { dogs } = useDogList(); return <DogList dogs={dogs} />;
}; export default DogListContainer;

DogListContainer.js

Nếu chúng ta không cần tái sử dụng presentational component có thể sử dụng hook trực tiếp vào như dưới đây. Việc này vẫn đảm bảo cô lập logic khỏi view.

import useDogList from "./DogListHook"; const DogList = () => { const { dogs } = useDogList(); return dogs?.map((dog, i) => ( <div style={{ width: "70%", margin: "auto" }} key={i}> <img src={dog} alt="dogs" width="100%" /> </div> ));
};
export default DogList;

DogList.js

Một số ưu điểm và nhược điểm

1. Ưu điểm

  • Tách các phần giúp dễ dàng hiểu ứng dụng hay UI tốt hơn.
  • Dễ dàng tái sử dụng. Có thể sử dụng các presentational component giống nhau bằng cách truyền các dữ liệu khác nhau qua props.
  • Dễ dàng sửa đổi các presentational component mà không cần chạm vào các logic của ứng dụng.

2. Nhược điểm

  • Hook giúp chúng ta có được các kết quả tương tự như Container component nhưng vẫn chưa hoàn toàn thay thế được.
  • Việc áp dụng pattern này trong các ứng dụng nhỏ đôi khi trở nên quá mức cần thiết.

Tham khảo

Bài viết tham khảo từ các nguồn

Đôi lời của tác giả

Đây là bài viết đầu tay của mình nên nếu mọi người thấy thú vị thì giúp up vote để lấy động lực ra tiếp bài sau, còn nếu mọi người chê hay có đôi lời góp ý thì cứ thỏa mái thả comment xuống dưới nhá. Thanks 😘

Bình luận

Bài viết tương tự

- vừa được xem lúc

Tổng hợp các bài hướng dẫn về Design Pattern - 23 mẫu cơ bản của GoF

Link bài viết gốc: https://gpcoder.com/4164-gioi-thieu-design-patterns/. Design Patterns là gì. Design Patterns không phải là ngôn ngữ cụ thể nào cả.

0 0 277

- vừa được xem lúc

Giới thiệu về Builder Design Pattern

Nguồn: refactoring.guru. Builder. Ý đồ.

0 0 34

- vừa được xem lúc

Một ví dụ nhỏ về Factory method

Trong bài viết trước mình đã giới thiệu tới các bạn về Abstract Factory pattern, các bạn quan tâm có thể theo dõi lại tại đây. Để tiếp tục về chủ đề design pattern trong bài viết này mình sẽ trình bày những khái niệm, ưu nhược điểm và các sử dụng của một creational design pattern khác đó là Factory

0 0 27

- vừa được xem lúc

Tôi đã dùng Service Pattern trong NuxtJS như thế nào ?

Giới thiệu. Trong quá trình làm VueJS NuxtJS hay thậm chí là Laravel mình cũng hay áp dụng các pattern như Service hoặc Repository.

0 0 59

- vừa được xem lúc

Hướng dẫn Adapter Design Pattern

Trong bài viết này, chúng ta sẽ cùng tìm hiểu về Adapter Design Pattern qua cấu trúc, cánh triển khai, ví dụ, ưu điểm nhược điểm và ứng dụng của nó. Đây là bài viết đầu tiên của mình nên sẽ không trán

1 1 53

- vừa được xem lúc

Giới thiệu về Prototype Design Pattern

Ý đồ. Prototype là một creational design pattern cho phép bạn sao chép các object hiện có mà không làm cho code của bạn phụ thuộc vào các class của chúng.

0 0 44