diff --git a/web/components/menu.react.js b/web/components/menu.react.js
index fedd647c7..3d968ba44 100644
--- a/web/components/menu.react.js
+++ b/web/components/menu.react.js
@@ -1,118 +1,119 @@
// @flow
import classnames from 'classnames';
import * as React from 'react';
import { useRenderMenu } from '../menu-provider.react';
import css from './menu.css';
type MenuVariant = 'thread-actions' | 'member-actions';
type MenuProps = {
+icon: React.Node,
+children?: React.Node,
+variant?: MenuVariant,
+onChange?: boolean => void,
};
function Menu(props: MenuProps): React.Node {
const buttonRef = React.useRef();
const {
renderMenu,
setMenuPosition,
closeMenu,
setCurrentOpenMenu,
currentOpenMenu,
} = useRenderMenu();
const { icon, children, variant = 'thread-actions', onChange } = props;
const ourSymbol = React.useRef(Symbol());
const menuActionListClasses = React.useMemo(
() =>
classnames(css.menuActionList, {
[css.menuActionListThreadActions]: variant === 'thread-actions',
[css.menuActionListMemberActions]: variant === 'member-actions',
}),
[variant],
);
const menuActionList = React.useMemo(
() =>
{children}
,
[children, menuActionListClasses],
);
const isOurMenuOpen = currentOpenMenu === ourSymbol.current;
const updatePosition = React.useCallback(() => {
if (buttonRef.current && isOurMenuOpen) {
const { top, left } = buttonRef.current.getBoundingClientRect();
setMenuPosition({ top, left });
}
}, [isOurMenuOpen, setMenuPosition]);
React.useEffect(() => {
if (!window) {
return undefined;
}
window.addEventListener('resize', updatePosition);
return () => window.removeEventListener('resize', updatePosition);
}, [updatePosition]);
React.useEffect(updatePosition, [updatePosition]);
const closeMenuCallback = React.useCallback(() => {
- closeMenu(menuActionList);
- }, [closeMenu, menuActionList]);
+ closeMenu(ourSymbol.current);
+ }, [closeMenu]);
React.useEffect(() => {
onChange?.(isOurMenuOpen);
}, [isOurMenuOpen, onChange]);
React.useEffect(() => {
if (!isOurMenuOpen) {
return undefined;
}
document.addEventListener('click', closeMenuCallback);
return () => {
document.removeEventListener('click', closeMenuCallback);
};
}, [closeMenuCallback, isOurMenuOpen]);
const prevActionListRef = React.useRef(null);
React.useEffect(() => {
if (!isOurMenuOpen) {
prevActionListRef.current = null;
return;
}
if (prevActionListRef.current === menuActionList) {
return;
}
renderMenu(menuActionList);
prevActionListRef.current = menuActionList;
}, [isOurMenuOpen, menuActionList, renderMenu]);
React.useEffect(() => {
- return () => closeMenu(prevActionListRef.current);
+ const ourSymbolValue = ourSymbol.current;
+ return () => closeMenu(ourSymbolValue);
}, [closeMenu]);
const onClickMenuCallback = React.useCallback(() => {
setCurrentOpenMenu(ourSymbol.current);
}, [setCurrentOpenMenu]);
if (React.Children.count(children) === 0) {
return null;
}
return (
);
}
export default Menu;
diff --git a/web/menu-provider.react.js b/web/menu-provider.react.js
index 55265467f..265223229 100644
--- a/web/menu-provider.react.js
+++ b/web/menu-provider.react.js
@@ -1,84 +1,106 @@
// @flow
import invariant from 'invariant';
import * as React from 'react';
import type { SetState } from 'lib/types/hook-types';
import css from './menu.css';
type MenuPosition = {
+top: number,
+left: number,
};
type Props = {
+children: React.Node,
};
type MenuContextType = {
- +renderMenu: SetState,
+ +renderMenu: React.Node => void,
+setMenuPosition: SetState,
- +closeMenu: React.Node => void,
- +currentOpenMenu: symbol,
- +setCurrentOpenMenu: SetState,
+ +closeMenu: (symbol) => void,
+ +currentOpenMenu: ?symbol,
+ +setCurrentOpenMenu: (symbol) => void,
};
const MenuContext: React.Context = React.createContext(
{
renderMenu: () => {},
setMenuPosition: () => {},
closeMenu: () => {},
- currentOpenMenu: Symbol(),
+ currentOpenMenu: null,
setCurrentOpenMenu: () => {},
},
);
+type Menu = {
+ +node: ?React.Node,
+ +symbol: ?symbol,
+};
+
function MenuProvider(props: Props): React.Node {
const { children } = props;
- const [menu, setMenu] = React.useState(null);
- const [currentOpenMenu, setCurrentOpenMenu] = React.useState(
- Symbol(),
- );
+ const [menu, setMenu] = React.useState