代码之家  ›  专栏  ›  技术社区  ›  bluebrooklynbrim

使用状态即时更新用户界面

  •  0
  • bluebrooklynbrim  · 技术社区  · 6 年前

    我正在尝试创建一个触发菜单打开的按钮。我最初的想法是设置按钮点击的状态,但发生的事情是,第一次点击对状态或类没有影响。更改在第二次和随后的单击时触发。

    我明白了 为什么? 可见性的状态不起作用(因为setstate是一个异步方法),但如何使它从最初的单击中更改?

    import React, { Component } from 'react';
    
    export default class Social extends Component {
      constructor() {
        super();
    
        // class of the div that will change
        this.menuVisibility = "social--icons_cntr--close"; 
    
        // managing the visibility of the menu items
        this.state = {
          visible: false
        };
    
        this.handleMouseDown = this.handleMouseDown.bind(this);
        this.toggleMenu = this.toggleMenu.bind(this);
      }
    
      handleMouseDown(e) {
        // if the state is visible, use the open class
        if (this.state.visible === true) {
          this.menuVisibility = "social--icons_cntr--open";
        } 
        // if the state is not visible use the close class
        else if (this.state.visible === false) {
          this.menuVisibility = "social--icons_cntr--close";
        }
        // call the the toggleMenu method
        this.toggleMenu();
        e.stopPropagation();
      }
    
      toggleMenu() {
        this.setState(
          { visible: !this.state.visible })
    
        console.log("visibility: ", this.state.visible);
        console.log("menuvis ", this.menuVisibility);
      }
    
      render() {
        return(
          <div className="social--cntr">
            <div className={this.menuVisibility}>
              <a className="social--icons-link" href="#">[X]</a>
            </div>
            <div className="social--btn-click social--btn-open"
              onMouseDown={this.handleMouseDown}>
              <span>+</span>
            </div>
          </div>
        )
      }
    }
    
    3 回复  |  直到 6 年前
        1
  •  1
  •   Chad Nehemiah    6 年前

    理解到 setState 异步的 那么这个结构应该会改变。将类绑定到基于状态的条件语句,例如

    <div className={{ (this.state.visible ? 'social--icons_cntr--open' : 'social--icons_cntr--close') }}>
    

    然后在你的 onMouseDown 函数只有 this.setState({{ !visible }}) . 这样,组件将绑定到状态并按照生命周期方法进行更新,即 ComponentDidUpdate

        2
  •  1
  •   nipuna777    6 年前

    setState 具有回调方法的第二个参数。您可以将代码放在那里,以便更新控制台记录的值。

    toggleMenu() {
      this.setState(
        { visible: !this.state.visible },
        () => {
          console.log("visibility: ", this.state.visible);
          console.log("menuvis ", this.menuVisibility);
        })
    }
    

    但是,在这种情况下,如果要更新视图,最好使用jsx模板中的状态值并以这种方式更新视图。

    您可以在模板中使用以下语法:

    <div className={this.state.visible ? 'social--icons_cntr--close' : 'social--icons_cntr--open'} >
    

    在此处查找stackblitz示例: https://stackblitz.com/edit/react-nszfds

        3
  •  0
  •   Rohith Murali    6 年前

    这不是因为 setState 异步的,但由于 logical error .
    您首先检查状态是真是假,然后只更改状态。 如果它是相反的,那么它就会起作用。

    是的,是的 设置状态 asynchronous 并有一个回调函数作为其第二个参数,在设置状态后执行操作。

    你可以使用下面的代码,

    handleMouseDown(e) {
    
      this.setState({ visible: !this.state.visible },()=>{
        // if the state is visible, use the open class
        if (this.state.visible === true) {
          this.menuVisibility = "social--icons_cntr--open";
        } 
        // if the state is not visible use the close class
        else if (this.state.visible === false) {
          this.menuVisibility = "social--icons_cntr--close";
        }
        })
        e.stopPropagation();
      }