React Error boundary unexpected behavior with material ui popover

346 Views Asked by At

There is a notifications component within a popover that makes a fetch call.

The connection fails and cannot reach the resources.

The error boundary component wraps the notifications component.

It is expected that after the connection fails, will show a custom component that says there is a problem along with a button to retry the connection.

However, the behavior of the error boundary is: It pauses while the popover is open (nothing is shown) and then just a few moments before it closes, it displays the custom component to retry the connection and the popover finishes closing.

export default function PopOver() {
  const [anchorNotificationEl, setAnchorNotificationEl] = React.useState(null);
  const popoverNotiRef = React.useRef(null);

  const isNotificationOpen = Boolean(anchorNotificationEl);

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

  const handleNotificationClose = () => {
    setAnchorNotificationEl(null);
  };

  const notificationId = 'notification-popover';
  return (
    <>
      <IconButtonCustom
        aria-label="show 17 new notifications"
        color="inherit"
        onClick={handleClick}
        id="notifications-icon"
      >
        <Badge
          badgeContent={0}
          color="secondary"
        >
          <NotificationsIcon
            fontSize="large"
          />
        </Badge>
      </IconButtonCustom>
      <Popover
        ref={popoverNotiRef}
        id={notificationId}
        open={isNotificationOpen}
        anchorEl={anchorNotificationEl}
        onClose={handleNotificationClose}
        anchorOrigin={{
          vertical: 'bottom',
          horizontal: 'center',
        }}
        transformOrigin={{
          vertical: 'top',
          horizontal: 'center',
        }}
        elevation={1}
      >
        <Notifications popoverRef={popoverNotiRef.current} />
      </Popover>
    </>
  );
}
class ErrorBoundary extends React.Component <Props, State> {
  constructor(props) {
    super(props);
    this.state = { error: null };
  }

  static getDerivedStateFromError(error): State {
    return { error };
  }

  componentDidCatch(error) {
    this.setState({ error });
  }

  render() {
    const { children, fallback } = this.props;
    const { error } = this.state;
    if (error) {
      if (fallback) {
        return fallback;
      }
      return <p>Something is wrong</p>;
    }
    return children;
  }
}

export default function NotificationWrapper({ popoverRef }: NWProps) {
  const [queryReference, loadQuery] = useQueryLoader(NotificationsQuery);

  useEffect(() => {
    loadQuery({
      count: 5,
    }, { fetchPolicy: 'store-and-network' });
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  return (
    <>
      <ErrorBoundary fallback={<RetryComponent loadQuery={loadQuery}/>}>
        {queryReference && (
        <Suspense fallback={<Loading />}>
          <NotificationsIntermediate queryRef={queryReference} popoverRef={popoverRef} />
        </Suspense>
        )}
      </ErrorBoundary>
    </>
  );
}
0

There are 0 best solutions below