REACT COOL PORTAL
Thích nó? ⭐️ Đánh giá trên GitHub hoặc Tweet về nó.
Xem Trực tiếp
⚡️ Thử ngay tại: https://react-cool-portal.netlify.app
Tính năng
- 🍒 Hiển thị một phần tử hoặc thành phần vào
<body>
hoặc một phần tử DOM cụ thể. - 🎣 Sử dụng React Portals với Hook.
- 🤖 Bộ điều khiển trạng thái tích hợp sẵn, lắng nghe sự kiện và nhiều tính năng hữu ích khác để cải thiện trải nghiệm phát triển.
- 🧱 Được sử dụng như một cấu trúc để xây dựng hook tùy chỉnh của bạn.
- 🧹 Tự động loại bỏ nơi chứa portal không được sử dụng. Không tạo ra bất kỳ lỗi DOM nào.
- 📜 Hỗ trợ TypeScript định nghĩa kiểu.
- 🗄️ Tương thích với việc render từ phía máy chủ.
- 🦔 Kích thước nhỏ (~ 1KB gzipped). Không có phụ thuộc ngoại trừ
react
vàreact-dom
.
Yêu cầu
Để sử dụng react-cool-portal
, bạn cần sử dụng react@16.8.0
hoặc phiên bản mới hơn có hỗ trợ hooks.
Cài đặt
Gói này được phân phối qua npm.
$ yarn add react-cool-portal
# or
$ npm install --save react-cool-portal
Sử dụng
Dưới đây là một số ví dụ cơ bản về cách hoạt động của nó. Bạn có thể tìm hiểu thêm về nó bằng cách kiểm tra API.
Trường Hợp Sử Dụng Cơ Bản
Chèn một phần tử hoặc thành phần vào vị trí khác trong DOM.
import usePortal from "react-cool-portal";
const App = () => {
const { Portal } = usePortal();
return (
<div>
<Portal>
<p>
Wow! I am rendered outside the DOM hierarchy of my parent component.
</p>
</Portal>
</div>
);
};
Theo mặc định, các phần tử con của portal được hiển thị vào <div id="react-cool-portal">
trong <body>
. Bạn có thể chỉ định phần tử DOM bạn muốn thông qua tùy chọn containerId
.
import usePortal from "react-cool-portal";
const App = () => {
const { Portal } = usePortal({ containerId: "my-portal-root" });
return (
<div>
<Portal>
<p>Now I am rendered into the specify element (id="my-portal-root").</p>
</Portal>
</div>
);
};
Lưu ý: Nếu phần tử chứa không tồn tại, chúng tôi sẽ tạo nó cho bạn.
Sử Dụng với Trạng Thái
react-cool-portal
cung cấp nhiều tính năng hữu ích, cho phép bạn xây dựng một thành phần với trạng thái. Ví dụ như modal, dropdown, tooltip, và nhiều tính năng khác.
import usePortal from "react-cool-portal";
const App = () => {
const { Portal, isShow, show, hide, toggle } = usePortal({
defaultShow: false, // The default visibility of portal, default is true
onShow: (e) => {
// Triggered when portal is shown
// The event object will be the parameter of `show(e?)`
},
onHide: (e) => {
// Triggered when portal is hidden
// The event object will be the parameter of `hide(e?)`, it maybe MouseEvent (on clicks outside) or KeyboardEvent (press ESC key)
},
});
return (
<div>
<button onClick={show}>Open Modal</button>
<button onClick={hide}>Close Modal</button>
<button onClick={toggle}>{isShow ? "Close" : "Open"} Modal</button>
<Portal>
<div className="modal" tabIndex={-1}>
<div
className="modal-dialog"
role="dialog"
aria-labelledby="modal-label"
aria-modal="true"
>
<div className="modal-header">
<h5 id="modal-label" className="modal-title">
Modal title
</h5>
</div>
<div className="modal-body">
<p>Modal body text goes here.</p>
</div>
</div>
</div>
</Portal>
</div>
);
};
🧹 Khi không có phần tử nào trong phần chứa, chúng tôi sẽ loại bỏ nó để tránh tạo lỗi DOM. Tuy nhiên, tính năng này có thể tắt bằng cách sử dụng tùy chọn autoRemoveContainer.
import usePortal from "react-cool-portal";
const App = () => {
const { Portal, isShow, show, hide, toggle } = usePortal({
defaultShow: false,
internalShowHide: false, // Disable the built-in show/hide portal functions, default is true
onShow: (e) => {
// Triggered when `isShow` is set to true
},
onHide: (e) => {
// Triggered when `isShow` is set to false
},
});
return (
<div>
<button onClick={show}>Open Modal</button>
<button onClick={hide}>Close Modal</button>
<button onClick={toggle}>{isShow ? "Close" : "Open"} Modal</button>
<Portal>
<div
// Now you can use the `isShow` state to handle the CSS animations
className={`modal${isShow ? " modal-open" : ""}`}
tabIndex={-1}
>
<div
className="modal-dialog"
role="dialog"
aria-labelledby="modal-label"
aria-modal="true"
>
<div className="modal-header">
<h5 id="modal-label" className="modal-title">
Modal title
</h5>
</div>
<div className="modal-body">
<p>Modal body text goes here.</p>
</div>
</div>
</div>
</Portal>
</div>
);
};
Ngoài ra, bạn cũng có thể điều khiển sự hiển thị của thành phần của mình thông qua React animation events hoặc transition events như tôi đã làm cho ứng dụng demo.
Xây Dựng Hook Tùy Chỉnh Của Bạn
Bạn đã mệt mỏi viết mã giống nhau một lần lặp lại? Đã đến lúc xây dựng hook của riêng bạn dựa trên react-cool-portal
, sau đó sử dụng nó ở bất kỳ đâu bạn muốn.
import { useCallback } from "react";
import usePortal from "react-cool-portal";
// Customize your hook based on react-cool-portal
const useModal = (options = {}) => {
const { Portal, isShow, ...rest } = usePortal({
...options,
defaultShow: false,
internalShowHide: false,
});
const Modal = useCallback(
({ children }) => (
<Portal>
<div className={`modal${isShow ? " modal-open" : ""}`} tabIndex={-1}>
{children}
</div>
</Portal>
),
[isShow]
);
return { Modal, isShow, ...rest };
};
// Use it wherever you want
const App = () => {
const { Modal, show, hide } = useModal();
return (
<div>
<button onClick={show}>Open Modal</button>
<button onClick={hide}>Close Modal</button>
<Modal>
<div
className="modal-dialog"
role="dialog"
aria-labelledby="modal-label"
aria-modal="true"
>
<div className="modal-header">
<h5 id="modal-label" className="modal-title">
Modal title
</h5>
</div>
<div className="modal-body">
<p>Modal body text goes here.</p>
</div>
</div>
</Modal>
</div>
);
};
Một vấn đề của ví dụ ở trên là CSS chuyển tiếp/hiệu ứng sẽ bị cắt đứt do việc tạo lại thành phần Portal
. Vì vậy, nếu bạn muốn áp dụng chuyển tiếp hoặc hiệu ứng vào phần tử bao bọc của hook tùy chỉnh, thì cần phải truyền isShow
từ props.
const useModal = (options = {}) => {
const { Portal, ...rest } = usePortal({
...options,
defaultShow: false,
internalShowHide: false,
});
const Modal = useCallback(
// Pass the `isShow` from props to prevent CSS transition/animation to be cut off
({ isShow, children }) => (
<Portal>
<div className={`modal${isShow ? " modal-open" : ""}`} tabIndex={-1}>
{children}
</div>
</Portal>
),
[]
);
return { Modal, ...rest };
};
Điều Kiện ESC hoặc Nhấp Chuột Bên Ngoài để Ẩn
Ẩn khi nhấn ESC hoặc nhấp chuột bên ngoài là một tính năng sẵn có của react-cool-portal
. Tuy nhiên, bạn có thể ẩn portal một cách có điều kiện dựa trên sự có mặt hoặc vắng mặt của một phần tử. Dưới đây là một ví dụ về modal lồng nhau:
import usePortal from "react-cool-portal";
const App = () => {
const [showChildModal, setShowChildModal] = useState(false);
const { Portal: ChildModal, show } = usePortal({ defaultShow: false });
const { Portal: ParentModal } = usePortal({
// Provide the class name of the child modal, so the parent modal will only be hidden after the child modal is hidden
escToHide: ["child-modal"],
// The same as above
clickOutsideToHide: ["child-modal"],
});
return (
<div>
<ParentModal>
<div>
<p>I'm parent modal.</p>
<button onClick={show}>Open Child Modal</button>
<ChildModal>
<div className="child-modal">
<p>I'm child modal.</p>
</div>
</ChildModal>
</div>
</ParentModal>
</div>
);
};
API
const returnObj = usePortal(parameterObj);
Đối tượng trả về
Nó được trả về với các thuộc tính sau.
Khóa | Kiểu | Mặc định | Mô tả |
---|---|---|---|
Portal | thành phần | Hiển thị các phần tử con vào một nút DOM tồn tại bên ngoài cấu trúc DOM của thành phần cha. | |
isShow | boolean | false |
Trạng thái hiển thị/ẩn của portal. |
show | function | Để hiển thị portal hoặc đặt isShow thành true . |
|
hide | function | Để ẩn portal hoặc đặt isShow thành false . |
|
toggle | function | Để chuyển đổi (hiển thị/ẩn) portal hoặc đặt isShow thành true/false . |
Đối tượng tham số (tùy chọn)
Khi sử dụng react-cool-portal
, bạn có thể cấu hình các tùy chọn sau thông qua tham số.
Khóa | Kiểu | Mặc định | Mô tả |
---|---|---|---|
containerId | string | react-cool-portal |
Bạn có thể chỉ định id của container riêng từ một phần tử DOM hiện có hoặc để hook này tự động tạo nó cho bạn. |
autoRemoveContainer | boolean | true |
Bật/tắt chức năng tự động loại bỏ container tích hợp sẵn. |
defaultShow | boolean | true |
Trạng thái hiển thị/ẩn ban đầu của portal. |
clickOutsideToHide | boolean | array | true |
escToHide | boolean | array | true |
internalShowHide | boolean | true |
Bật/tắt chức năng show/hide portal tích hợp sẵn, cung cấp cách linh hoạt để xử lý portal của bạn. |
onShow | function | Kích hoạt khi portal được hiển thị hoặc isShow được đặt thành true . |
|
onHide | function | Kích hoạt khi portal bị ẩn hoặc isShow được đặt thành false . |
Bài viết / Bài đăng trên Blog
💡 Nếu bạn đã viết bất kỳ bài đăng blog hoặc bài viết nào về
react-cool-portal
, vui lòng mở một PR để thêm nó vào đây.
- Nổi bật trên React Newsletter #206.
Chi tiết tải về:
Tác giả: wellyshen
Nguồn: https://github.com/wellyshen/react-cool-portal
Giấy phép: MIT license