diff --git a/web/components/menu.react.js b/web/components/menu.react.js --- a/web/components/menu.react.js +++ b/web/components/menu.react.js @@ -61,8 +61,8 @@ React.useEffect(updatePosition, [updatePosition]); const closeMenuCallback = React.useCallback(() => { - closeMenu(menuActionList); - }, [closeMenu, menuActionList]); + closeMenu(ourSymbol.current); + }, [closeMenu]); React.useEffect(() => { onChange?.(isOurMenuOpen); @@ -93,7 +93,8 @@ }, [isOurMenuOpen, menuActionList, renderMenu]); React.useEffect(() => { - return () => closeMenu(prevActionListRef.current); + const ourSymbolValue = ourSymbol.current; + return () => closeMenu(ourSymbolValue); }, [closeMenu]); const onClickMenuCallback = React.useCallback(() => { diff --git a/web/menu-provider.react.js b/web/menu-provider.react.js --- a/web/menu-provider.react.js +++ b/web/menu-provider.react.js @@ -15,11 +15,11 @@ +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( @@ -27,48 +27,70 @@ 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({ node: null, symbol: null }); const [position, setPosition] = React.useState({ top: 0, left: 0, }); - const closeMenu = React.useCallback((menuToClose: React.Node) => { - setCurrentOpenMenu(Symbol()); - setMenu(oldMenu => { - if (oldMenu === menuToClose) { - return null; - } else { - return oldMenu; + const setMenuSymbol = React.useCallback( + (newSymbol: symbol) => + setMenu(prevMenu => { + if (prevMenu.symbol === newSymbol) { + return prevMenu; + } + return { node: null, symbol: newSymbol }; + }), + [], + ); + + const setMenuNode = React.useCallback( + (newMenuNode: React.Node) => + setMenu(prevMenu => { + if (prevMenu.node === newMenuNode) { + return prevMenu; + } + return { ...prevMenu, node: newMenuNode }; + }), + [], + ); + + const closeMenu = React.useCallback((menuToCloseSymbol: symbol) => { + setMenu(currentMenu => { + if (currentMenu.symbol === menuToCloseSymbol) { + return { node: null, symbol: null }; } + return currentMenu; }); }, []); const value = React.useMemo( () => ({ - renderMenu: setMenu, + renderMenu: setMenuNode, setMenuPosition: setPosition, closeMenu, - setCurrentOpenMenu, - currentOpenMenu, + setCurrentOpenMenu: setMenuSymbol, + currentOpenMenu: menu.symbol, }), - [closeMenu, currentOpenMenu], + [closeMenu, menu.symbol, setMenuNode, setMenuSymbol], ); return ( <> {children}
- {menu} + {menu.node}
);