EmojiButton: Eliminate usage of createPortal

This commit is contained in:
Scott Nonnenberg 2023-01-18 16:09:18 -08:00 committed by GitHub
parent 86488b97b9
commit b0e2d22750
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 39 additions and 47 deletions

View file

@ -6,7 +6,6 @@ import type { MutableRefObject } from 'react';
import classNames from 'classnames';
import { get, noop } from 'lodash';
import { Manager, Popper, Reference } from 'react-popper';
import { createPortal } from 'react-dom';
import { Emoji } from './Emoji';
import type { Props as EmojiPickerProps } from './EmojiPicker';
import { EmojiPicker } from './EmojiPicker';
@ -55,17 +54,17 @@ export const EmojiButton = React.memo(function EmojiButtonInner({
variant = EmojiButtonVariant.Normal,
}: Props) {
const [open, setOpen] = React.useState(false);
const [popperRoot, setPopperRoot] = React.useState<HTMLElement | null>(null);
const buttonRef = React.useRef<HTMLButtonElement | null>(null);
const popperRef = React.useRef<HTMLDivElement | null>(null);
const refMerger = useRefMerger();
const handleClickButton = React.useCallback(() => {
if (popperRoot) {
if (open) {
setOpen(false);
} else {
setOpen(true);
}
}, [popperRoot, setOpen]);
}, [open, setOpen]);
const handleClose = React.useCallback(() => {
setOpen(false);
@ -87,22 +86,6 @@ export const EmojiButton = React.memo(function EmojiButtonInner({
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(() => {
if (!open) {
return noop;
@ -113,9 +96,12 @@ export const EmojiButton = React.memo(function EmojiButtonInner({
handleClose();
return true;
},
{ containerElements: [popperRoot, buttonRef], name: 'EmojiButton' }
{
containerElements: [popperRef, buttonRef],
name: 'EmojiButton',
}
);
}, [open, handleClose, popperRoot]);
}, [open, handleClose]);
// Install keyboard shortcut to open emoji picker
React.useEffect(() => {
@ -167,31 +153,30 @@ export const EmojiButton = React.memo(function EmojiButtonInner({
</button>
)}
</Reference>
{open && popperRoot
? createPortal(
<Popper placement="top-start" strategy="fixed">
{({ ref, style }) => (
<EmojiPicker
ref={ref}
i18n={i18n}
style={style}
onPickEmoji={ev => {
onPickEmoji(ev);
if (closeOnPick) {
handleClose();
}
}}
doSend={doSend}
onClose={handleClose}
skinTone={skinTone}
onSetSkinTone={onSetSkinTone}
recentEmojis={recentEmojis}
/>
)}
</Popper>,
popperRoot
)
: null}
{open ? (
<div ref={popperRef}>
<Popper placement="top-start" strategy="fixed">
{({ ref, style }) => (
<EmojiPicker
ref={ref}
i18n={i18n}
style={style}
onPickEmoji={ev => {
onPickEmoji(ev);
if (closeOnPick) {
handleClose();
}
}}
doSend={doSend}
onClose={handleClose}
skinTone={skinTone}
onSetSkinTone={onSetSkinTone}
recentEmojis={recentEmojis}
/>
)}
</Popper>
</div>
) : null}
</Manager>
);
});

View file

@ -2443,6 +2443,13 @@
"updated": "2022-06-14T22:04:43.988Z",
"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",
"path": "ts/components/installScreen/InstallScreenChoosingDeviceNameStep.tsx",