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

时间:2017-10-19 09:02:50

标签: javascript reactjs create-react-app

在一个简单的reactJS类中,this.setState()实际上并没有设置状态。我知道它是异步调用的,但即使组件再次渲染,状态也不会发生变异。因此,this.state.showModal在安装组件时({按预期)为false,然后true为“永远”。

这是一个简单的例子:

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

这是模态组件:

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

但是,当我用这样的超时替换hideModal函数时:

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

状态发生变异并按预期呈现。

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

编辑:调用hideModal和showModal添加

2 个答案:

答案 0 :(得分:0)

你也在父元素上有一个public void onBillingSetupFinished(int billingResponseCode) { Purchase.PurchasesResult result = billingClient.queryPurchases(INAPP); List<Purchase> purchasesList = result.getPurchasesList(); isPremiumUnlocked = !purchasesList.isEmpty(); } 处理程序,调用click并将状态更改为true。

当您点击showModal按钮时,会调用close函数,这会将状态更改为hideModal,但该点击也会传播到父元素,这将调用{{ 1}}再次使它成为false。因此它始终保持showModal

解决方案:从父元素中删除true点击处理程序,并将其放在您想要的位置(我想您希望它在true上)。

答案 1 :(得分:0)

由于没有玩家可以玩,我会猜测。

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

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

尝试在event.stopPropagation函数中添加hideModal(),它可能会有用。

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

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