From 55d36cd8172dbf43bc48f988952d5a03344a1b71 Mon Sep 17 00:00:00 2001 From: martes <96113508+martesi@users.noreply.github.com> Date: Fri, 5 Jul 2024 02:10:21 +0800 Subject: [PATCH] refactor(usePortal): use `createPortal` directly (#368) --- packages/utils/src/usePortal.tsx | 53 ++++++-------------------------- 1 file changed, 10 insertions(+), 43 deletions(-) diff --git a/packages/utils/src/usePortal.tsx b/packages/utils/src/usePortal.tsx index 1f3ad044..bb966781 100644 --- a/packages/utils/src/usePortal.tsx +++ b/packages/utils/src/usePortal.tsx @@ -1,47 +1,14 @@ -import React, { useState, useEffect, ReactPortal, useRef } from 'react'; +import { PropsWithChildren, useCallback, useState } from 'react'; import { createPortal } from 'react-dom'; -import { createRoot, Root } from 'react-dom/client'; - -interface State { - render: (props: { children: React.ReactNode }) => ReactPortal | null; - remove: (elm?: HTMLElement) => void; -} export const usePortal = () => { - const ref = useRef(); - const [container] = React.useState(() => { - const el = document.createElement('div'); - ref.current = createRoot(el); - return el; - }); - const [portal, setPortal] = useState({ - render: () => null, - remove: () => null, - }); - - const ReactCreatePortal = React.useCallback<(elmm: HTMLDivElement) => State>((elmm) => { - const Portal: State['render'] = ({ children }) => { - if (!children) return null; - return createPortal(children, elmm); - }; - const remove: State['remove'] = (elm) => { - // https://stackoverflow.com/a/74445760/1334703 - const timeout = setTimeout(() => { - elm && ref.current?.unmount(); - clearTimeout(timeout); - }); - }; - return { render: Portal, remove }; - }, []); - - useEffect(() => { - if (container) portal.remove(); - const newPortal = ReactCreatePortal(container); - setPortal(newPortal); - return () => { - newPortal.remove(container); - }; - }, [container]); - - return { Portal: portal.render, container }; + const [container] = useState(() => document.createElement('div')); + const Portal = useCallback( + function Portal({ children }: PropsWithChildren) { + return createPortal(children, container); + }, + [container], + ); + + return { Portal, container }; };