tajo/react-portal

Using state to conditionally render components causing PortalWithState modal to close when closeOnOutsideClick true

davidjamescarter opened this issue · 2 comments

I have found that when using the PortalWithState with closeOnOutsideClick my modal will close when using state to conditionally render components.

PortalWithState closeOnOutsideClick closeOnEsc defaultOpen>
    {({ closePortal, portal }) =>
        portal(
        <Modal closePortal={closePortal} key="confirmation-modal">
            <JobPreviewModal
            bid={bid}
            jobOffer={jobOffer}
            schedule={schedule}
            taxonomiesByClassification={taxonomiesByClassification}
            />
        </Modal>,
        )
    }
</PortalWithState>`
class JobPreviewModal extends PureComponent {
  state = {
    editing: false,
    some: false,
  };

  toggleEditingState = () => {
    this.setState(previousState => {
      return {
        editing: !previousState.editing,
        some: !previousState.some,
      };
    });
  };

  render() {
    const { jobOffer, bid, schedule, taxonomiesByClassification } = this.props;

    const { editing } = this.state;

    return !editing ? (
      <JobPreview
        bid={bid}
        jobOffer={jobOffer}
        schedule={schedule}
        taxonomiesByClassification={taxonomiesByClassification}
        toggleEditingState={this.toggleEditingState}
      />
    ) : (
      <h1>Editing</h1>
    );
  }
}
class Modal extends Component {
  render() {
    const { children, closePortal, small } = this.props;

    console.log('children', children);
    return (
      <ModalWrapper small={small}>
        <div>
          {children.length
            ? children.map(child => React.cloneElement(child))
            : React.cloneElement(children)}
          <button className="close" onClick={closePortal}>
            Close
          </button>
        </div>
      </ModalWrapper>
    );
  }
}

Changing state to edit: true. Causes modal to close.

Has anyone else experienced, have a fix? Going to see if I can figure out a fix locally and PR if so.

I've found setting closeOnOutsideClick and triggering openPortal doesn't open the portal at all..

@davidcarter-me i might have a solution for you.

When you click stuff inside the portal, changing state on a parent element causes a render on the click target. When this event bubbles to the Portal, the contains check inside the portals closeOnOutsideClick cannot reference the e.target

I worked around this by wrapping the state changing method in requestAnimationFrame, so the closeOnOutsideClick resolver runs first, and then the state change.

Hope that helps