简体   繁体   English

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

[英]Why does ReactJS sets state when calling setState inside setTimeout?

In a simple reactJS class, this.setState() didn't actually set the state. 在一个简单的reactJS类中,this.setState()实际上并未设置状态。 I know it is called asynchronously but even when the component renders again, the state wasn't mutated. 我知道它被异步调用,但是即使组件再次呈现,状态也不会发生变化。 So this.state.showModal is false when component is mounted (as expected) then it is true "forever". 因此,在安装组件时(如预期的那样), this.state.showModalfalse ,然后“永远”为true

here's a simple example : 这是一个简单的例子:

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

Here's the Modal Component : 这是模态组件:

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

But, when I replace the hideModal function with a timeout like this : 但是,当我用这样的超时替换hideModal函数时:

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

The state is mutated and rendered as intended. 状态被突变并按预期方式呈现。

I'm just wondering why ReactJS could possibly reset state internally or prevent a state from mutating ? 我只是想知道为什么ReactJS可能在内部重置状态或阻止状态发生变化?

Edit : Calls to hideModal and showModal added 编辑:添加了对hideModal和showModal的调用

You have a click handler on the parent element too which call the showModal and change the state to true. 在父元素上也有一个click处理程序,它会调用showModal并将状态更改为true。

When you click close button, that will call hideModal function, which will change the state to false but that click will propagate to parent element as well, which will call showModal which make it true again. 当您单击close按钮时,这将调用hideModal函数,该函数会将状态更改为false但是该单击也将传播到父元素,这将调用showModal使其再次变为true Therefore it always remains true . 因此,它始终是true

Solution: Remove showModal click handler from the parent element and put it where exactly you want it to be (i guess you want it on + ). 解决方案:从父元素中删除showModal单击处理程序,并将其放置在您想要的位置(我想在+上放置它)。

Since there is no plunker to play around, I am going to take a guess. 由于没有小玩意儿在玩,所以我要猜测一下。

div being the parent of <Modal> , when click event is triggered on the Modal , it is also being propagated to div . div<Modal>的父级,当在Modal上触发click事件时,它也将传播到div So showModal state is set to false by hideModal() function and set back to true by showModal() function. 因此,由hideModal()函数将showModal状态设置为false ,并通过showModal()函数将其设置为true

When hideModal() uses setTimeout() , it is getting called after showModal() is called. hideModal()使用setTimeout() ,将在调用showModal()之后调用它。

Try adding event.stopPropagation in hideModal() function, it might work. 尝试在hideModal()函数中添加event.stopPropagation ,它可能会起作用。

Alternatively, you should add showModal() as onClick handler for the + sign instead of whole parent div. 另外,您应该将showModal()作为+符号(而不是整个父div showModal()添加为onClick处理程序。 Please find the code below: 请在下面找到代码:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM