ampproject / amp-react-prototype

A scratch pad to experiment with React rendered AMP Components
Apache License 2.0
36 stars 9 forks source link

Controlled vs uncontrolled lightbox #43

Open dvoytenko opened 4 years ago

dvoytenko commented 4 years ago

AMP's lightboxes are components with completely separate "roots" and lifecycle. They only supply imperative APIs such as:

lightbox.open().then(result => {
  // Lightbox has closed with a possible return value.
});

A classical approach in React would use a controlled style:

export function Demo() {
  const [open, setOpen] = React.useState(false);
  return (
    <div>
      <Button onClick={() => setOpen(true)}>Open</Button>
      <XDialog open={open} onClose={_ => setOpen(false)}>...</XDialog>
    </div>
  );
}

There are some benefits when using a controlled style. But there are also some nuances to consider:

  1. Open state has to be controlled. This expands the required API surface. I.e. to use the XDialog, one must manage open state, supplied as a property, and handle onClose.
  2. Out-of-lightbox closing has to be non-vetoable. This can probably be remedied by an additional onCloseRequest event callback.
  3. AMP element itself has to be uncontrolled since DOM elements do not have controlled/uncontrolled concept. Thus we'd have to remap the controlled state to imperative DOM APIs.