为什么ReactJS在setTimeout中调用setState时会设置状态?

问题描述:

在一个简单的reactJS类中,this.setState()并没有真正设置状态。我知道它是异步调用的,但即使组件再次渲染时,状态也不会发生变化。所以this.state.showModalfalse组件安装(如预期),那么它是true“永远”。为什么ReactJS在setTimeout中调用setState时会设置状态?

这里有一个简单的例子:

class MyComponent extends Component { 
    constructor (props) { 
    super(props) 

    this.state = { 
     showModal: false 
    } 

    this.showModal = this.showModal.bind(this) 
    this.hideModal = this.hideModal.bind(this) 
    } 
    showModal() { 
    this.setState({ showModal: true }) 
    } 
    hideModal() { 
    this.setState({ showModal: false }) 
    } 
    render() { 
    console.log(this.state.showModal) // Outputs true even after the hideModal() call 

    return (
     <Components> 
     <div onClick={this.showModal}> 
      { 
      this.state.showModal === true 
      ? <Modal 
       handles={handles} 
       close={this.hideModal} 
      /> 
      : '+' 
      } 
     </div> 
     </Components> 
    ) 
    } 
} 

这里的模态分量:

setTimeout(() => this.setState({ showModal: false }), 0)

class Modal extends Component { 
    render() { 
    return (
     <div className='configurator-modal'> 
     <button className='close' onClick={this.props.close}> x </button> 
     Modal 
     </div> 
    ) 
    } 
} 

但是,当我有这样的超时更换hideModal功能

状态发生变化并呈现如预期的那样。

我只是想知道为什么ReactJS可能可以在内部重置状态或防止状态发生变异?

编辑:调用hideModal和添加的ShowModal

+2

您需要显示如何调用'hidemodal'? – Panther

+0

你能告诉我们你如何调用'hideModal'方法吗? – vs1682

+0

我编辑了我的帖子,对不起,我试图简化代码太多。 – 3Dos

既然没有蹦蹦跳跳,我会猜测。

div<Modal>的父级,当点击事件在Modal上被触发时,它也被传播到div。所以showModal状态被设置为false通过hideModal()函数并且被设置回true通过showModal()函数。

hideModal()使用setTimeout()时,在调用showModal()后调用它。

尝试在hideModal()函数中添加event.stopPropagation函数,它可能工作。

或者,您应该添加showModal()作为onClick处理程序的+符号而不是整个父div。请找到以下代码:

<Components> 
    <div> 
     { 
     this.state.showModal === true 
     ? <Modal 
      handles={handles} 
      close={this.hideModal} 
     /> 
     : <div onClick={this.showModal}>'+'</div> 
     } 
    </div> 
    </Components> 
+0

非常感谢。这工作完美。我绝对没有想到,但它似乎超级逻辑! – 3Dos

你有父元素在click处理过其称之为showModal,改变状态设置为true。

当您单击close按钮,将调用hideModal功能,这将状态改变为false但点击将传播到父元素为好,这将调用showModal这使其再次true。因此它始终保持true

解决方案:从父元素删除showModal点击处理程序,并把它放在正是你希望它是(我猜你想它+)。