ReactJS - Portals: Cánh cửa dẫn đến những chiều không gian mới trong các ứng dụng React của bạn

Xin chào, những nhà phát triển React đầy tham vọng! Hôm nay, chúng ta sẽ bắt đầu một hành trình đầy thú vị vào thế giới của React Portals. Hãy tưởng tượng bạn đang xây dựng một ngôi nhà (ứng dụng React của bạn), và bỗng nhiên bạn nhận ra rằng bạn cần một lối đi bí mật để vận chuyển thứ gì đó từ phòng này sang phòng khác mà không cần đi qua hành lang chính. Đó chính xác là điều mà React Portals làm cho các thành phần của bạn!

ReactJS - Portals

React Portals là gì?

React Portals cung cấp một cách thức hàng đầu để渲染 các thành phần con vào một nút DOM nằm ngoài hierachy DOM của thành phần cha. Nói đơn giản hơn, nó giống như tạo ra một lỗ黑洞 cho phép bạn render một thành phần ở một nơi khác trong cây DOM, mặc dù nó vẫn là một phần của hierachy thành phần React của bạn.

Tại sao chúng ta cần Portals?

Bạn có thể tự hỏi, "Tại sao tôi không thể render thành phần của mình wherever tôi muốn?" Well, trong hầu hết các trường hợp, bạn có thể! Nhưng có những tình huống mà Portals rất hữu ích:

  1. Các hộp thoại modal
  2. Tooltips
  3. Các menu浮动
  4. Các widget cần thoát khỏi container của chúng

Hãy cùng tìm hiểu sâu hơn về cách Portals hoạt động và cách sử dụng chúng.

Tạo Portal đầu tiên của bạn

Để tạo một Portal, chúng ta sử dụng phương thức ReactDOM.createPortal(). Dưới đây là một ví dụ cơ bản:

import React from 'react';
import ReactDOM from 'react-dom';

function MyPortalComponent() {
return ReactDOM.createPortal(
<h1>Tôi được render ở một nơi khác!</h1>,
document.getElementById('portal-root')
);
}

Trong ví dụ này, chúng ta đang tạo một Portal để render một phần tử <h1> vào một nút DOM có id là 'portal-root'. Nút này nên tồn tại ở đâu đó trong HTML của bạn, ngoài phần tử root chính của ứng dụng React.

Hãy phân tích phương thức ReactDOM.createPortal():

  1. Tham số đầu tiên là phần tử React bạn muốn render.
  2. Tham số thứ hai là phần tử DOM nơi bạn muốn render nó.

Một ví dụ thực tế: Hộp thoại Modal

Hãy tạo một ví dụ thực tế hơn - một hộp thoại modal xuất hiện trên nội dung ứng dụng của bạn.

import React, { useState } from 'react';
import ReactDOM from 'react-dom';

function Modal({ isOpen, onClose, children }) {
if (!isOpen) return null;

return ReactDOM.createPortal(
<div className="modal-overlay">
<div className="modal-content">
{children}
<button onClick={onClose}>Đóng</button>
</div>
</div>,
document.getElementById('modal-root')
);
}

function App() {
const [isModalOpen, setIsModalOpen] = useState(false);

return (
<div>
<h1>Chào mừng đến với ứng dụng của tôi</h1>
<button onClick={() => setIsModalOpen(true)}>Mở Modal</button>
<Modal isOpen={isModalOpen} onClose={() => setIsModalOpen(false)}>
<h2>Đây là một Modal</h2>
<p>Nó được render ngoài cây React chính!</p>
</Modal>
</div>
);
}

Trong ví dụ này, chúng ta đã tạo một thành phần Modal có thể tái sử dụng và sử dụng Portal để render nội dung của nó. Thành phần App kiểm soát tính hiển thị của modal bằng cách sử dụng hook useState của React.

Hãy phân tích những gì đang xảy ra:

  1. Thành phần Modal kiểm tra xem nó có nên mở (isOpen prop) hay không.
  2. Nếu mở, nó tạo một Portal để render nội dung của nó vào phần tử 'modal-root'.
  3. Nội dung modal bao gồm một nút đóng để kích hoạt prop onClose.
  4. Trong thành phần App, chúng ta sử dụng state để kiểm soát tính hiển thị của modal.

Sự nổi bọt của sự kiện qua Portals

Một khía cạnh thú vị của Portals là ngay cả khi chúng có thể render nội dung ở bất kỳ nơi nào trong cây DOM, các sự kiện vẫn nổi bọt qua cây React như mong đợi. Hãy xem một ví dụ:

import React, { useState } from 'react';
import ReactDOM from 'react-dom';

function Parent() {
const [clicks, setClicks] = useState(0);

const handleClick = () => {
setClicks(clicks + 1);
};

return (
<div onClick={handleClick}>
<h1>Số lần nhấp: {clicks}</h1>
<Portal>
<Child />
</Portal>
</div>
);
}

function Portal({ children }) {
return ReactDOM.createPortal(
children,
document.getElementById('portal-root')
);
}

function Child() {
return <button>Nhấp vào tôi!</button>;
}

Trong ví dụ này, việc nhấp vào nút bên trong Portal vẫn sẽ kích hoạt bộ xử lý nhấp trong thành phần Parent, tăng số lần nhấp. Behavior này rất hữu ích vì nó duy trì sự lan truyền sự kiện như mong đợi, bất kể thành phần được render thực sự ở đâu trong DOM.

Các nguyên tắc tốt nhất và các 고려

Khi sử dụng Portals, hãy nhớ các điểm sau:

  1. Khả năng truy cập: Đảm bảo rằng nội dung Portal của bạn khả năng truy cập, đặc biệt là cho người dùng máy quét màn hình.
  2. Xử lý sự kiện: Nhớ rằng các sự kiện nổi bọt qua cây React, không phải cây DOM.
  3. Thiết kế: Nội dung Portal có thể cần các 고려 thiết kế riêng biệt.
  4. Dọn dẹp: Đừng quên dọn dẹp Portals khi thành phần không còn được gắn kết.

Các phương thức Portal

Dưới đây là bảng các phương thức chính liên quan đến React Portals:

Phương thức Mô tả
ReactDOM.createPortal(child, container) Tạo một portal. child là bất kỳ con cái renderable nào của React, và container là một phần tử DOM.
ReactDOM.unmountComponentAtNode(container) Loại bỏ một thành phần đã gắn kết khỏi DOM và dọn dẹp các bộ xử lý sự kiện và state của nó.

Kết luận

React Portals là một tính năng mạnh mẽ cho phép bạn thoát khỏi hierachy thành phần truyền thống khi render. Chúng đặc biệt hữu ích cho việc tạo modals, tooltips và các UI element khác cần " thoát ra " khỏi container của chúng.

Nhớ rằng, với quyền lực lớn đi kèm với trách nhiệm lớn! Sử dụng Portals một cách thông minh và luôn xem xét tác động đến cấu trúc và khả năng truy cập của ứng dụng bạn.

Chúc các bạn may mắn và các Portal của bạn luôn dẫn đến những chiều không gian mới trong các ứng dụng React của bạn!

Credits: Image by storyset