我有一个类似这样的小组件(下面的代码简化为所需的部分),在更新状态时表现得很奇怪。
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
);
}
}
状态会在组件中的其他位置更新,因此单击按钮时,属性为true
。
单击也会触发setState
函数(将执行回调),但是状态不会更新。
test: true
并在单击按钮时将该属性更改为false
也会触发showStuff
道具变为false。因此,当我进行奇怪的修改时,它就可以工作。
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>
);
}
}
答案 0 :(得分:3)
通过编写onClick={this.setState({showStuff: false})}
,您实际上是在渲染按钮后立即调用setState
。
您要给函数提供对onClick
的引用,而不是在渲染时立即调用它。
<button onClick={() => this.setState({showStuff: false})} />
如果您的按钮位于您不想在同一点击上运行的带有点击侦听器的另一个元素内,则必须确保click事件不会传播到父对象。
<button
onClick={(event) => {
event.stopPropagation();
this.setState({showStuff: false});
}}
/>
答案 1 :(得分:0)
实际上onClick属性需要一个函数,您已经在提供函数调用,因此setState将在每次呈现组件时调用,而不是在单击时调用。
尝试一下:
<button onClick={() => this.setState({showStuff: false})} />
应该表现出预期的效果:)
答案 2 :(得分:0)
当我更新showStuff true时,效果很好(请参见下面的更新代码。)。我的猜测是应该设置showStuff的代码:true无法正常工作。我还在按钮中添加了一些文字。
import React from 'react'
import ReactDOM from 'react-dom'
class Componenent extends React.Component {
constructor(props) {
super(props);
this.state = {showStuff: true};
}
render() {
return(
<div>
{this.state.showStuff && (
<button onClick={() => this.setState({showStuff: false})} > This is a button</button>
)}
</div>
);
}
}
ReactDOM.render(<Componenent />,
document.getElementById('root')
);
点击之前
点击后