javascript - 当从依赖状态的元素调用时,setState() 不会更改状态以呈现

标签 javascript reactjs state

我有一个像这样的小组件(下面的代码被简化为所需的部分)在更新状态时表现得很奇怪。

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/

相关文章:

Javascript 表单输入检索

javascript - 禁用 Windows 中的按键

javascript - firebase.storage() 不带参数或使用 Firebase App 实例

reactjs - React useEffect从api获取时无限循环

javascript - jquery 滚动效果不适用于 iphone

css - 是否可以在 react 中使用 css 自定义 FullCalendar?

javascript - React Yup 验证两个字段的长度之和

java - 在 GXT 中保存对象状态

java - 跨多个请求周期保留组件状态

javascript - 如何在vue.js的组件中运行bootstrap的轮播间隔功能?