Store portal elements as state instead of refs (#1212)

i ❤️ dan abramov
This commit is contained in:
Brendan Allan 2023-08-13 10:27:42 -07:00 committed by GitHub
parent c86a728a1a
commit a74e9aa341
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 29 additions and 36 deletions

View file

@ -1,18 +1,18 @@
import { PropsWithChildren, RefObject, createContext, useContext, useRef } from 'react'; import { PropsWithChildren, createContext, useContext, useState } from 'react';
interface QuickPreviewContext { interface QuickPreviewContext {
ref: RefObject<HTMLDivElement>; ref: HTMLDivElement | null;
} }
const QuickPreviewContext = createContext<QuickPreviewContext | null>(null); const QuickPreviewContext = createContext<QuickPreviewContext | null>(null);
export const QuickPreviewContextProvider = ({ children }: PropsWithChildren) => { export const QuickPreviewContextProvider = ({ children }: PropsWithChildren) => {
const ref = useRef<HTMLDivElement>(null); const [ref, setRef] = useState<HTMLDivElement | null>(null);
return ( return (
<QuickPreviewContext.Provider value={{ ref }}> <QuickPreviewContext.Provider value={{ ref }}>
{children} {children}
<div ref={ref} /> <div ref={setRef} />
</QuickPreviewContext.Provider> </QuickPreviewContext.Provider>
); );
}; };

View file

@ -172,8 +172,7 @@ export default memo(
)} )}
</div> </div>
{quickPreviewCtx.ref.current && {quickPreviewCtx.ref && createPortal(<QuickPreview />, quickPreviewCtx.ref)}
createPortal(<QuickPreview />, quickPreviewCtx.ref.current)}
</> </>
); );
} }

View file

@ -1,21 +1,21 @@
import { RefObject, createContext, useContext, useRef } from 'react'; import { createContext, useContext, useState } from 'react';
import { Outlet } from 'react-router'; import { Outlet } from 'react-router';
import TopBar from '.'; import TopBar from '.';
interface TopBarContext { interface TopBarContext {
left: RefObject<HTMLDivElement>; left: HTMLDivElement | null;
right: RefObject<HTMLDivElement>; right: HTMLDivElement | null;
} }
const TopBarContext = createContext<TopBarContext | null>(null); const TopBarContext = createContext<TopBarContext | null>(null);
export const Component = () => { export const Component = () => {
const left = useRef<HTMLDivElement>(null); const [left, setLeft] = useState<HTMLDivElement | null>(null);
const right = useRef<HTMLDivElement>(null); const [right, setRight] = useState<HTMLDivElement | null>(null);
return ( return (
<TopBarContext.Provider value={{ left, right }}> <TopBarContext.Provider value={{ left, right }}>
<TopBar leftRef={left} rightRef={right} /> <TopBar leftRef={setLeft} rightRef={setRight} />
<Outlet /> <Outlet />
</TopBarContext.Provider> </TopBarContext.Provider>
); );

View file

@ -2,17 +2,13 @@ import { ReactNode } from 'react';
import { createPortal } from 'react-dom'; import { createPortal } from 'react-dom';
import { useTopBarContext } from './Layout'; import { useTopBarContext } from './Layout';
interface Props { export const TopBarPortal = (props: { left?: ReactNode; right?: ReactNode }) => {
left?: ReactNode;
right?: ReactNode;
}
export const TopBarPortal = ({ left, right }: Props) => {
const ctx = useTopBarContext(); const ctx = useTopBarContext();
return ( return (
<> <>
{left && ctx.left.current && createPortal(left, ctx.left.current)} {props.left && ctx.left && createPortal(props.left, ctx.left)}
{right && ctx.right.current && createPortal(right, ctx.right.current)} {props.right && ctx.right && createPortal(props.right, ctx.right)}
</> </>
); );
}; };

View file

@ -1,33 +1,31 @@
import { RefObject } from 'react'; import { Ref } from 'react';
import { NavigationButtons } from './NavigationButtons'; import { NavigationButtons } from './NavigationButtons';
import SearchBar from './SearchBar'; import SearchBar from './SearchBar';
export const TOP_BAR_HEIGHT = 46; export const TOP_BAR_HEIGHT = 46;
interface Props { interface Props {
leftRef?: RefObject<HTMLDivElement>; leftRef?: Ref<HTMLDivElement>;
rightRef?: RefObject<HTMLDivElement>; rightRef?: Ref<HTMLDivElement>;
} }
const TopBar = (props: Props) => { const TopBar = (props: Props) => (
return ( <div
<div data-tauri-drag-region
data-tauri-drag-region className="
className="
duration-250 top-bar-blur absolute left-0 top-0 z-50 flex duration-250 top-bar-blur absolute left-0 top-0 z-50 flex
h-[46px] w-full flex-row items-center justify-center overflow-hidden h-[46px] w-full flex-row items-center justify-center overflow-hidden
border-b border-sidebar-divider bg-app/90 px-3.5 border-b border-sidebar-divider bg-app/90 px-3.5
transition-[background-color,border-color] ease-out transition-[background-color,border-color] ease-out
" "
> >
<div data-tauri-drag-region className="flex flex-1 flex-row items-center"> <div data-tauri-drag-region className="flex flex-1 flex-row items-center">
<NavigationButtons /> <NavigationButtons />
<div ref={props.leftRef} /> <div ref={props.leftRef} />
</div>
<SearchBar />
<div className="flex-1" ref={props.rightRef} />
</div> </div>
); <SearchBar />
}; <div className="flex-1" ref={props.rightRef} />
</div>
);
export default TopBar; export default TopBar;