Hey @pzuraq ,
Not sure if this is a bug or just me not understanding the nuances of the libraries involved here, but I wrote a helper function to manage the opening, closing, and anchoring of a Material UI Menu, and to my surprise it didn't work.
Here is the helper function (and the call to the function):
import { reactive, signal } from "signalium":
export function createMenuState() {
const rawAnchorEl = signal<HTMLElement | null>(null);
const anchorEl = reactive(() => rawAnchorEl.value);
const canShow = reactive(() => !!anchorEl());
return { anchorEl, canShow, open, close };
function open(value: HTMLElement) {
rawAnchorEl.value = value;
}
function close() {
rawAnchorEl.value = null;
}
}
export const sortMenuState = createMenuState();
Here is the menu component:
import { Check as CheckIcon } from "@mui/icons-material";
import { ListItemText, Menu, MenuItem } from "@mui/material";
import { component } from "signalium/react";
import { sortMenuState as state } from "./toolbar-state";
function SortMenu() {
return (
<Menu
open={state.canShow()}
anchorEl={state.anchorEl()}
anchorOrigin={{ vertical: "bottom", horizontal: "left" }}
transformOrigin={{ vertical: "top", horizontal: "left" }}
onClose={state.close}
>
<MenuItem onClick={state.close}>
<CheckIcon />
<ListItemText>Unit Name A-Z</ListItemText>
</MenuItem>
<MenuItem onClick={state.close}>
<ListItemText>Unit Name Z-A</ListItemText>
</MenuItem>
</Menu>
);
}
export default component(SortMenu);
Here is the button that spawns the menu:
import { FilterList as SortIcon } from "@mui/icons-material";
import { Button } from "@mui/material";
import { component } from "signalium/react";
import SortMenu from "./SortMenu";
import { sortMenuState } from "./toolbar-state";
function Toolbar() {
return (
<>
<Button
variant="text"
startIcon={<SortIcon />}
color="secondary"
onClick={e => {
sortMenuState.open(e.currentTarget);
}}
>
Sort
</Button>
<SortMenu />
</>
);
}
export default component(Toolbar);
If I look at the DOM in the dev tools, I see an expander very briefly appear for this element:
<span class="MuiTouchRipple-root css-r3djoj-MuiTouchRipple-root"></span>`
However, the menu itself never appears or appears so briefly that I cannot see it.
I added a bunch of console logs and confirmed that when I push the menu button, the value of the rawAnchorEl signal does indeed get set to the expected HTML element, and the SortMenu component does re-render. Even though the menu immediately disappears, though, rawAnchorEl never returns to null (i.e., the close mutation function never gets called).
I tried to use Anthropic Claude to debug this, and it "thought" the problem was something to do with MUI's use of React Portals:
MUI's Menu uses React portals and internal state management that might not play well with Signalium's reactive wrappers. The reactive() function might not be triggering the necessary React re-renders for the portal to mount.
If I ditch all the Signalium code and just follow MUI's example in the docs, which shows the anchor element being stored in a local useState, everything works fine.
Any insight on what could be going on here and if it's possible to fix this without reverting to useState?
Hey @pzuraq ,
Not sure if this is a bug or just me not understanding the nuances of the libraries involved here, but I wrote a helper function to manage the opening, closing, and anchoring of a Material UI
Menu, and to my surprise it didn't work.Here is the helper function (and the call to the function):
Here is the menu component:
Here is the button that spawns the menu:
If I look at the DOM in the dev tools, I see an expander very briefly appear for this element:
However, the menu itself never appears or appears so briefly that I cannot see it.
I added a bunch of console logs and confirmed that when I push the menu button, the value of the
rawAnchorElsignal does indeed get set to the expected HTML element, and theSortMenucomponent does re-render. Even though the menu immediately disappears, though,rawAnchorElnever returns tonull(i.e., theclosemutation function never gets called).I tried to use Anthropic Claude to debug this, and it "thought" the problem was something to do with MUI's use of React Portals:
If I ditch all the Signalium code and just follow MUI's example in the docs, which shows the anchor element being stored in a local
useState, everything works fine.Any insight on what could be going on here and if it's possible to fix this without reverting to
useState?