我有一个像这样的小组件(下面的代码被简化为所需的部分)在更新状态时表现得很奇怪。
class Componenent extends React.Component {
constructor(props) {
super(props);
this.state = {showStuff: false};
}
render() {
return(
//Markup
{this.state.showStuff && (
<button onClick={() => this.setState({showStuff: false})} />
)}
// More Markup
);
}
}
状态会在组件的其他地方更新,所以当按钮被点击时,prop 为 true
。
单击也会触发 setState
函数(执行回调),但状态不会更新。
我的猜测是它不会更新,因为该函数是由一个直接依赖于 state 属性是否可见的元素调用的。
我发现向状态添加另一个 Prop
test: true
并在单击按钮时将该属性更改为 false
也会触发 showStuff
Prop 改为假。所以当我做出奇怪的黑客攻击时它会起作用。 有人可以向我解释这种奇怪的行为吗?我不明白为什么上面的代码片段没有按预期工作。
这是整个组件:
class ElementAdd extends React.Component {
constructor(props) {
super(props);
this.defaultState = {
showElementWheel: false,
test: true
};
this.state = this.defaultState;
}
handleAddCardClick() {
if (this.props.onCardAdd) {
this.props.onCardAdd({
type: ElementTypes.card,
position: this.props.index
});
}
}
handleAddKnowledgeClick() {
if (this.props.onCardAdd) {
this.props.onCardAdd({
type: ElementTypes.knowledge,
position: this.props.index
});
}
}
handleTabPress(e) {
if (e.key === 'Tab') {
e.preventDefault();
let target = null;
if (e.shiftKey) {
if (e.target.previousSibling) {
target = e.target.previousSibling;
} else {
target = e.target.nextSibling;
}
} else {
if (e.target.nextSibling) {
target = e.target.nextSibling;
} else {
target = e.target.previousSibling;
}
}
target.focus();
}
}
hideElementWheel() {
// This is somehow the only option to trigger the showElementWheel
this.setState({ test: false });
}
render() {
return (
<div
className="element-add"
style={{ opacity: this.props.invisible ? 0 : 1 }}
onClick={() => this.setState(prevSate => ({ showElementWheel: !prevSate.showElementWheel }))}
>
<PlusIcon className="element-add__icon" />
{this.state.showElementWheel && (
<React.Fragment>
<div className="element-add__wheel">
<button
autoFocus
className="element-add__circle"
onClick={this.handleAddCardClick.bind(this)}
onKeyDown={this.handleTabPress.bind(this)}
title="New element"
>
<ViewModuleIcon className="element-add__element-icon" />
</button>
<button
className="element-add__circle"
onClick={this.handleAddKnowledgeClick.bind(this)}
onKeyDown={this.handleTabPress.bind(this)}
title="New knowledge-element"
>
<FileIcon className="element-add__element-icon" />
</button>
</div>
<div
className="element-add__close-layer"
onClick={() => {
this.hideElementWheel();
}}
/>
</React.Fragment>
)}
</div>
);
}
}
最佳答案
通过编写 onClick={this.setState({showStuff: false})}
,您实际上是在按钮呈现后立即调用 setState
。
您想给 onClick
一个函数引用,而不是在渲染时立即调用它。
<button onClick={() => this.setState({showStuff: false})} />
如果您的按钮位于另一个元素内,您不想在同一次点击时运行点击监听器,则必须确保点击事件不会传播到父级。
<button
onClick={(event) => {
event.stopPropagation();
this.setState({showStuff: false});
}}
/>
关于javascript - 当从依赖状态的元素调用时,setState() 不会更改状态以呈现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51271857/