【问题标题】:React Modal Does Not Close In Between Loading ContentReact Modal 在加载内容之间不会关闭
【发布时间】:2017-12-26 23:31:09
【问题描述】:

我正在使用这个反应模式插件:https://github.com/reactjs/react-modal 我需要在页面加载时在模式中显示一组对象。当第一项显示用户单击按钮时,模态的 isOpen 属性设置为 false。每个项目都有一个道具 showModal 将值提供给模态的 isOpen。随着用户不断单击,我不断将当前对象的值设置为 false,然后为下一个对象设置为 true。 这一切都很好,但问题是覆盖和对话窗口留在屏幕上,只有模式中的内容被更新。我希望模态完全关闭并打开以显示数组中下一个对象的内容。我不得不将我的代码剥离为下面的简化版本:

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>
    );
  }
}

【问题讨论】:

  • 您的问题不清楚。你能解释一下你想要更好地完成什么吗?
  • @AlexanderHiggins 好的,所以你知道模态如何打开并且有一个覆盖?我希望每次将 isOpen 设置为 false 时关闭它,因为我要通过产品。现在它没有发生,当我浏览产品时,带有覆盖的 Modal 保持打开状态。有意义吗?
  • 您的模态框 isOpen 有一个 showModal 的道具,但在您的 ProductItemModal 中,我根本看不到您设置 showModal。你的意思是showPopUpshowModal
  • @Simon 来自 this.props.showModal,在父组件 showPopUp={currentProduct['showModal']} 是从父组件发送的。所有这些状态变化都在 showNextPopUp() 中处理
  • 我已经对 isOpen 的值进行了故障排除,那里一切正常。我想我还需要在这里做点别的事情。模态打开正常,当最后一个产品的 showModal 属性设置为 false 时,它​​会关闭。但在这两者之间它保持打开状态,只是刷新产品内容。

标签: javascript reactjs react-modal


【解决方案1】:

为您的所有问题找到了解决方法并创建了这个codepen link。应该是这样的,

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"));

如果有帮助,请告诉我。

更新的代码笔https://codepen.io/anon/pen/rzVQrw?editors=0110

【讨论】:

  • 感谢您的帮助,但我没有看到模态框。当我点击下一步时,它只是循环浏览产品。
  • 您需要添加额外的 CSS 以根据需要显示 Modal。我用另一个codepen link 更新了帖子,并添加了一些样式。查看此official react-modal link 了解更多示例。
【解决方案2】:

你需要调用 ProductItemModal 的 setState() 来关闭 Model。否则,尽管更改了 isOpen,但不会重新渲染 UI。

【讨论】:

    【解决方案3】:

    您可能知道,React 维护一个虚拟 DOM,并且每次状态或道具更改时,它都会比较浏览器的 DOM(实际 DOM)和虚拟 DOM(React 维护的)之间的差异,并且每次更改时都会在您的代码中进行比较isOpen 属性你所做的只是改变模型组件的道具,这就是为什么 React 只更新实际模型的内部内容

    要完全关闭并重新打开模型,您需要对代码进行一些小改动

    除了在ProductsModal 中只返回一个模型组件之外,您需要执行类似的操作,以便反应知道此模式已关闭而其他模式已打开 关键属性很重要 性能理由read more

    class ProductsModal extends React.Component {
     .
     .
     .
    
    showModals() {
        let products = this.state.products;
        //A different function saves the array of product objects in the state so 
    
    
        if (products.length > 0) {
          return (
            //return list of all modal component
            products.map((product) =>
               <ProductItemModal 
                  product={product}
                  showNextPopUp={() => this.showNextPopUp(product.productId)}
                  showPopUp={product['showModal']}
                  key={product.productId}
                  />
            )
          );
        //showModal is a boolean for each product that sets the value of isOpen
        }
      }
    
     .
     . 
     .
    }
    

    您在这里所做的只是返回多个模态,当一个模型获得 isOpen 道具时,false 已关闭,而另一个女巫获得 true 已打开,现在反应知道有两种不同的模态,因为 关键道具

    【讨论】:

      【解决方案4】:

      另一种解决方法是使用setTimeout。实现如下-

      class ProductItemModal extends React.Component {
        render() {
          const { showModal, product, selectNextProductFunc, 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={() => selectNextProductFunc(product)}>Next</button>
            </ReactModal>
          );
        }
      }
      
      class ProductsModal extends React.Component {
        constructor() {
          super();
      
          this.state = {
            products: [
              {id: 1, name: "Mac"},
              {id: 2, name: "iPhone"},
              {id: 3, name: "iPod"},
            ],
            productId: null,
            showModal: true,
          };
        }
      
        handleProductItemModalClose(product) {
          //backdrop click or escape click handling here
          console.log(`Modal closing from Product - ${product.name}`);
        }
      
      
        showModals() {
          const { products, productId, showModal} = this.state;
          //A different function saves the array of product objects in the state so 
          //I can show them one by one
          const getProduct = function(){
            if(productId){
              return products.find((i) => i.id === productId);
            }else{
              return products[0]; // first element
            }
          }
      
      
            return <ProductItemModal 
                    product={getProduct()}
                    selectNextProductFunc={this.selectNextProductFunc.bind(this)}
                    showModal={showModal}
                    onClose={() => this.handleProductItemModalClose()}
                    />;
          //showModal is a boolean for each product that sets the value of isOpen
      
        }
      
        selectNextProductFunc(currentProduct) {
          const { products} = this.state;
          this.setState({
            showModal: false
          });
      
          const currentProductIndex = products.findIndex((i) => i.id === currentProduct.id);
          const modifiedIndex = 0;
          if(products[currentProductIndex + 1]){
            this.setState({
               productId : products[currentProductIndex + 1].id,
            });
          }else{
            this.setState({
               productId : modifiedIndex,
            });
          }
      
          setTimeout(() => {
              this.setState({
                showModal: true
              })
          }, 1000);
      
        }
      
        render() {
          return(
            <div>
              {this.showModals()}
            </div>
          );
        }
      }
      
      ReactDOM.render(<ProductsModal />, document.getElementById("main"));
      

      jsbin

      【讨论】:

        猜你喜欢
        • 2020-10-15
        • 1970-01-01
        • 2018-01-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多