Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Modal Does Not Close In Between Loading Content

I'm using this react modal plugin: https://github.com/reactjs/react-modal and I need to show an array of objects in the modal on page load. When the first item shows user clicks a button so isOpen prop is set to false for Modal. Each item has a prop showModal that feeds the value to isOpen for the Modal. As the user keeps clicking I keep setting the value on the current object to false and then set it true for the next object. This is all working fine but the problem is that the overlay and dialog window stays on screen and only content within the modal is updated. I would like the modal to fully close and open to show content of the next object in array. I had to strip out my code to a simplified version below:

class ProductsModal extends React.Component {
  constructor(props) {
    super(props);
    this.remindMeHandler = this.remindMeHandler.bind(this);

    this.state = {
      products: [],
      modalId: 0
    };
  }

showModals() {
    let products = this.state.products;
    //A different function saves the array of product objects in the state so 
    //I can show them one by one

    let currentProduct = products[this.state.popUpId];

    if (products.length > 0) {
      return <ProductItemModal 
              product={currentProduct}
              showNextPopUp={() => this.showNextPopUp(currentProduct.productId)}
              showPopUp={currentProduct['showModal']}
              />;
    //showModal is a boolean for each product that sets the value of isOpen
    }
  }

  showNextPopUp() {
      //All this does is sets the "showModal" property to false for current 
     //product and sets it to true for next product so it shows in the Modal
  }


render() {
    return(
      <div>
        {this.showModals()}
      </div>
    );
  }
}

class ProductItemModal extends React.Component {
  constructor(props) {
    super(props);
  }

  render() {
    return(
      <Modal 
        isOpen={this.props.showModal}
        contentLabel="Product"
        id={this.props.product.productId}
        >
        <div>
         Product Data......
        </div>
      </Modal>
    );
  }
}
like image 215
sayayin Avatar asked Jul 21 '17 04:07

sayayin


People also ask

How do I use React-modal?

General Usage. The only required prop for the modal object is isOpen, which indicates whether the modal should be displayed. The following is an example of using react-modal specifying all the possible props and options: import ReactModal from 'react-modal'; <ReactModal isOpen={ false /* Boolean describing if the modal should be shown or not.

How to close a modal in Joomla?

To close the modal, simply call the handleClose () function inside the onLoginFormSubmit () function body. There you go! Now, there are still a couple of places you need to use the handleClose function in the Modal component. In this section, you can find the entire source code for your reference.

What are the keys of reactmodalportal?

It has two keys, `overlay` and `content`. See the `Styles` section for more details. */} contentLabel={ "Example Modal" /* String indicating how the content container should be announced to screenreaders */} portalClassName={ "ReactModalPortal" /* String className to be applied to the portal.

Does the Modal open onclick or not?

Sign in to your account I have copied the code directly and the Modal opens nicely onClick but once open the modal does not close. Please provide a repro if you think there's a bug here.


1 Answers

Had a workaround for all your problems and created this codepen link. It would be like this,

class ProductItemModal extends React.Component {
  render() {
    const { showModal, product, showNextModal, onClose } = this.props;

    return(
      <ReactModal 
        isOpen={showModal}
        contentLabel="Product"
        onRequestClose={() => onClose()}
        >
        <p>
          <b>Product Id</b> - {product.id}, <b>Product Name</b> - {product.name}
        </p>
        <button onClick={() => showNextModal()}>Next</button>
      </ReactModal>
    );
  }
}

class ProductsModal extends React.Component {
  constructor() {
    super();

    this.state = {
      products: [
        {id: 1, name: "Mac", showModal: true},
        {id: 2, name: "iPhone", showModal: false},
        {id: 3, name: "iPod", showModal: false},
      ],
      modalId: 0
    };
  }

  handleProductItemModalClose(product) {
    //backdrop click or escape click handling here
    console.log(`Modal closing from Product - ${product.name}`);
  }

  showModals() {
    const { products, modalId } = this.state;
    //A different function saves the array of product objects in the state so 
    //I can show them one by one

    let currentProduct = products[modalId];

    if(currentProduct) {
      return <ProductItemModal 
              product={currentProduct}
              showNextModal={() => this.showNextModal(currentProduct.id)}
              showModal={currentProduct["showModal"]}
              onClose={() => this.handleProductItemModalClose(currentProduct)}
              />;
    //showModal is a boolean for each product that sets the value of isOpen
    }
  }

  showNextModal(currentProductId) {
    const { products, modalId } = this.state;

    var isLastModal = false;
    if(modalId === products.length - 1) {
      isLastModal = true;
    }

    var clonedProducts = [...products];
    var currentIndex = clonedProducts.findIndex(product => product.id === currentProductId);
    var newIndex = currentIndex + 1;
    clonedProducts[currentIndex].showModal = false;
    if(!isLastModal) {
      clonedProducts[newIndex].showModal = true;
    } else {
      //comment the following lines if you don't wanna show modal again from the start
      newIndex = 0;
      clonedProducts[0].showModal = true;
    }
      //All this does is sets the "showModal" property to false for current 
     //product and sets it to true for next product so it shows in the Modal
    this.setState({
      products: clonedProducts
    }, () => {
      this.setState({
        modalId: newIndex
      });
    });
  }

  render() {
    return(
      <div>
        {this.showModals()}
      </div>
    );
  }
}

ReactDOM.render(<ProductsModal />, document.getElementById("main"));

Let me know if it helps.

Updated codepen: https://codepen.io/anon/pen/rzVQrw?editors=0110

like image 170
Abraham Gnanasingh Avatar answered Oct 22 '22 02:10

Abraham Gnanasingh