2

I've got some problem with omit re-render while click button which open Dialog component. Currently I use useState flag which toggle my Dialog component but I must avoid re-rendering because there's expensive operations on big data.

Anyone know approach how to Open Dialog by button Open and Close Dialog by click on Dialog's button Exit.

const Item = () => {

    const popupRef = useRef()

    const dialog = () => {
        return(
            <Dialog ref={popupRef}
                    keepMounted
                    fullWidth
                    maxWidth="md"
                    aria-labelledby="alert-dialog-slide-title"
                    aria-describedby="alert-dialog-slide-description">
                <DialogTitle id="alert-dialog-slide-title">
                    <WrapperDialogHeader>Filters</WrapperDialogHeader>
                    <WrapperDialogCloseBtn>
                        <IconButton aria-label="close" >
                            <CloseIcon />
                        </IconButton>
                    </WrapperDialogCloseBtn>
                </DialogTitle>
                <DialogContent>
                   Something 
                </DialogContent>
                <DialogActions>
                    <Button variant="outlined"
                            // onClick={ What handler here? }
                            color="primary">
                        <WrapperDialogOptionBtn>Exit</WrapperDialogOptionBtn>
                    </Button>
                </DialogActions>
            </Dialog>
        )
    }

    return(
        <>
            <IconButton onClick={ /* What method here */ }>
                <Typography variant="body1" color="primary">
                    <FilterListIcon fontSize="small" color="primary"/><WrapperFontSpecialSmall>Filters</WrapperFontSpecialSmall>
                </Typography>
            </IconButton>
            { dialog() }
        </>

Methods like popupRef.current.click() not exist in ES6 I suppose.
How to build mechanism which toggle dialog without re-render whole component Item.

41 72 6c
  • 1,600
  • 5
  • 19
  • 30
Dominic
  • 105
  • 1
  • 4
  • 13

1 Answers1

3

Move the dialog to its own component and wrap in memo()

const Dialog = ({ open, onClose }) => {

  return (
    <Dialog
      keepMounted // why? you said the content is huge, so why keep it mounted
      fullWidth
      maxWidth="md"
      aria-labelledby="alert-dialog-slide-title"
      aria-describedby="alert-dialog-slide-description"
      open={open}
      onClose={onClose}
    >
      <DialogTitle id="alert-dialog-slide-title">
        <WrapperDialogHeader>Filters</WrapperDialogHeader>
        <WrapperDialogCloseBtn>
          <IconButton aria-label="close" >
            <CloseIcon />
          </IconButton>
        </WrapperDialogCloseBtn>
      </DialogTitle>
      <DialogContent>
        Something
      </DialogContent>
      <DialogActions>
        <Button variant="outlined" onClick={onClose} color="primary">
          <WrapperDialogOptionBtn>Exit</WrapperDialogOptionBtn>
        </Button>
      </DialogActions>
    </Dialog>
  )
};

export default memo(Dialog); // IMPORTANT

In the Item component,

const Item = () => {
  const [dialogOpen, setDialogOpen] = useState(false);

  const handleDialogOpen = () => setDialogOpen(true);
  
  // prevent function being recreated on state change
  const handleDialogClose = useCallback(() => setDialogOpen(false), []);

  return (
   <>
      <IconButton onClick={handleDialogOpen}>
        <Typography variant="body1" color="primary">
          <FilterListIcon fontSize="small" color="primary" /><WrapperFontSpecialSmall>Filters</WrapperFontSpecialSmall>
        </Typography>
      </IconButton>
      <Dialog open={dialogOpen} onClose={handleDialogClose} />
   </>
  );
}

Sidenote, it appears the dialog contains some sort of filter UI, presumably one or more lists. You may want to have a look at react-window if you are going to create long lists.

Matthew Kwong
  • 2,548
  • 2
  • 11
  • 22