简体   繁体   中英

MUI Popper Component with Props keeps closing component on re-render

I am curious how to architect a component leveraging MUI's Popover component when there are dynamic props getting passed to a controlled Slider component inside of the Popover component — as well as the anchor element also getting dynamically updated as the value changes getting passed-down from a higher order component.

What is happening is that when the controlled child is updated by the user, it dispatches the change higher up the chain, driving new values down, which then re-renders the component, setting the anchorEl back to null. Here's a quick video in action:

在此处输入图像描述

I'm sure there is something straightforward I could do to avoid this. Any help is appreciated!

Here is abbreviated code:

function Component({ dynamicProps }) {
  const [anchorEl, setAnchorEl] = React.useState(null);
  const { dispatch } = useContext();

  const handleClick = (event) => {
    setAnchorEl(event.currentTarget);
  };

  const handleClose = () => {
    setAnchorEl(null);
  };

  const handleChange = (_, newValue) => {
      dispatch({
        body: newValue
      });
  };

  const open = Boolean(anchorEl);
  const id = open ? "simple-popover" : undefined;

  return (
    <div>
      <Button
        onClick={handleClick}
        label={dynamicProps.label}
      ></Button>
      <Popover
        id={id}
        open={open}
        anchorEl={anchorEl}
        onClose={handleClose}
      >
        <Box sx={{ minWidth: "200px", mx: 2 }}>
          <Slider
            value={dynamicProps.value}
            onChange={handleChange}
          />
        </Box>
      </Popover>
    </div>
  );
}

I have tried separating the Slider into another component, to avoid the re-render, and using my context's state to grab the values that I need, hover that point seems moot, since I still need to reference the anchorEl in the child, and since the trigger also is leveraging dynamic props, it will re-render and keep null-ing the anchorEl.

Ok team. Figured this one all-by-myself

Here's what you don't want to do: If you're going to use context — use it both for dispatching and grabbing state. Don't drill-down state from a parent component that will trigger a re-render. For both the button label and the controlled Slider, as long as you use the state insider the Component function through your context hook, you won't trigger a re-render, making your popper disappear from the re-render.

Do this

export default function Assumption({ notDynamicProps }) {
  const [anchorEl, setAnchorEl] = React.useState(null);
  const { dispatch, state } = useRentalCalculator();

Not this

export default function Assumption({ dynamicProps, notDynamicProps }) {
  const [anchorEl, setAnchorEl] = React.useState(null);
  const { dispatch } = useRentalCalculator();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM