EmojiButton: Eliminate usage of createPortal
This commit is contained in:
parent
86488b97b9
commit
b0e2d22750
2 changed files with 39 additions and 47 deletions
|
@ -6,7 +6,6 @@ import type { MutableRefObject } from 'react';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { get, noop } from 'lodash';
|
import { get, noop } from 'lodash';
|
||||||
import { Manager, Popper, Reference } from 'react-popper';
|
import { Manager, Popper, Reference } from 'react-popper';
|
||||||
import { createPortal } from 'react-dom';
|
|
||||||
import { Emoji } from './Emoji';
|
import { Emoji } from './Emoji';
|
||||||
import type { Props as EmojiPickerProps } from './EmojiPicker';
|
import type { Props as EmojiPickerProps } from './EmojiPicker';
|
||||||
import { EmojiPicker } from './EmojiPicker';
|
import { EmojiPicker } from './EmojiPicker';
|
||||||
|
@ -55,17 +54,17 @@ export const EmojiButton = React.memo(function EmojiButtonInner({
|
||||||
variant = EmojiButtonVariant.Normal,
|
variant = EmojiButtonVariant.Normal,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const [open, setOpen] = React.useState(false);
|
const [open, setOpen] = React.useState(false);
|
||||||
const [popperRoot, setPopperRoot] = React.useState<HTMLElement | null>(null);
|
|
||||||
const buttonRef = React.useRef<HTMLButtonElement | null>(null);
|
const buttonRef = React.useRef<HTMLButtonElement | null>(null);
|
||||||
|
const popperRef = React.useRef<HTMLDivElement | null>(null);
|
||||||
const refMerger = useRefMerger();
|
const refMerger = useRefMerger();
|
||||||
|
|
||||||
const handleClickButton = React.useCallback(() => {
|
const handleClickButton = React.useCallback(() => {
|
||||||
if (popperRoot) {
|
if (open) {
|
||||||
setOpen(false);
|
setOpen(false);
|
||||||
} else {
|
} else {
|
||||||
setOpen(true);
|
setOpen(true);
|
||||||
}
|
}
|
||||||
}, [popperRoot, setOpen]);
|
}, [open, setOpen]);
|
||||||
|
|
||||||
const handleClose = React.useCallback(() => {
|
const handleClose = React.useCallback(() => {
|
||||||
setOpen(false);
|
setOpen(false);
|
||||||
|
@ -87,22 +86,6 @@ export const EmojiButton = React.memo(function EmojiButtonInner({
|
||||||
emojiButtonApi.current = api;
|
emojiButtonApi.current = api;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create popper root and handle outside clicks
|
|
||||||
React.useEffect(() => {
|
|
||||||
if (open) {
|
|
||||||
const root = document.createElement('div');
|
|
||||||
setPopperRoot(root);
|
|
||||||
document.body.appendChild(root);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
document.body.removeChild(root);
|
|
||||||
setPopperRoot(null);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return noop;
|
|
||||||
}, [open, setOpen, setPopperRoot, handleClose]);
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (!open) {
|
if (!open) {
|
||||||
return noop;
|
return noop;
|
||||||
|
@ -113,9 +96,12 @@ export const EmojiButton = React.memo(function EmojiButtonInner({
|
||||||
handleClose();
|
handleClose();
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
{ containerElements: [popperRoot, buttonRef], name: 'EmojiButton' }
|
{
|
||||||
|
containerElements: [popperRef, buttonRef],
|
||||||
|
name: 'EmojiButton',
|
||||||
|
}
|
||||||
);
|
);
|
||||||
}, [open, handleClose, popperRoot]);
|
}, [open, handleClose]);
|
||||||
|
|
||||||
// Install keyboard shortcut to open emoji picker
|
// Install keyboard shortcut to open emoji picker
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
|
@ -167,8 +153,8 @@ export const EmojiButton = React.memo(function EmojiButtonInner({
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</Reference>
|
</Reference>
|
||||||
{open && popperRoot
|
{open ? (
|
||||||
? createPortal(
|
<div ref={popperRef}>
|
||||||
<Popper placement="top-start" strategy="fixed">
|
<Popper placement="top-start" strategy="fixed">
|
||||||
{({ ref, style }) => (
|
{({ ref, style }) => (
|
||||||
<EmojiPicker
|
<EmojiPicker
|
||||||
|
@ -188,10 +174,9 @@ export const EmojiButton = React.memo(function EmojiButtonInner({
|
||||||
recentEmojis={recentEmojis}
|
recentEmojis={recentEmojis}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Popper>,
|
</Popper>
|
||||||
popperRoot
|
</div>
|
||||||
)
|
) : null}
|
||||||
: null}
|
|
||||||
</Manager>
|
</Manager>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
@ -2443,6 +2443,13 @@
|
||||||
"updated": "2022-06-14T22:04:43.988Z",
|
"updated": "2022-06-14T22:04:43.988Z",
|
||||||
"reasonDetail": "Handling outside click"
|
"reasonDetail": "Handling outside click"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"rule": "React-useRef",
|
||||||
|
"path": "ts/components/emoji/EmojiButton.tsx",
|
||||||
|
"line": " const popperRef = React.useRef<HTMLDivElement | null>(null);",
|
||||||
|
"reasonCategory": "usageTrusted",
|
||||||
|
"updated": "2023-01-18T22:32:43.901Z"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"rule": "React-useRef",
|
"rule": "React-useRef",
|
||||||
"path": "ts/components/installScreen/InstallScreenChoosingDeviceNameStep.tsx",
|
"path": "ts/components/installScreen/InstallScreenChoosingDeviceNameStep.tsx",
|
||||||
|
|
Loading…
Reference in a new issue