为什么 ReactJS 在 setTimeout 中调用 setState 时会设置状态?
Why does ReactJS sets state when calling setState inside setTimeout?
在一个简单的 reactJS class 中,this.setState() 实际上并没有设置状态。我知道它是异步调用的,但即使组件再次呈现,状态也没有发生变化。所以 this.state.showModal
是 false
当组件被安装时(如预期的那样)那么它是 true
"forever".
这是一个简单的例子:
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 的调用
您在父元素上也有一个 click
处理程序,它调用 showModal
并将状态更改为 true。
当您单击 close
按钮时,将调用 hideModal
函数,这会将状态更改为 false
但该单击也会传播到父元素,这将调用showModal
再次成为 true
。因此它始终保持 true
.
解决方案: 从父元素中删除 showModal
click handler 并把它放在你想要的地方(我想你想要它在 +
).
既然没有渣男可以玩,我就来猜一猜。
div
作为 <Modal>
的父级,当在 Modal
上触发点击事件时,它也会传播到 div
。因此 showModal
状态由 hideModal()
函数设置为 false
并由 showModal()
函数设置回 true
。
当 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>
在一个简单的 reactJS class 中,this.setState() 实际上并没有设置状态。我知道它是异步调用的,但即使组件再次呈现,状态也没有发生变化。所以 this.state.showModal
是 false
当组件被安装时(如预期的那样)那么它是 true
"forever".
这是一个简单的例子:
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 的调用
您在父元素上也有一个 click
处理程序,它调用 showModal
并将状态更改为 true。
当您单击 close
按钮时,将调用 hideModal
函数,这会将状态更改为 false
但该单击也会传播到父元素,这将调用showModal
再次成为 true
。因此它始终保持 true
.
解决方案: 从父元素中删除 showModal
click handler 并把它放在你想要的地方(我想你想要它在 +
).
既然没有渣男可以玩,我就来猜一猜。
div
作为 <Modal>
的父级,当在 Modal
上触发点击事件时,它也会传播到 div
。因此 showModal
状态由 hideModal()
函数设置为 false
并由 showModal()
函数设置回 true
。
当 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>