this.setState()与绑定事件无法正常工作

时间:2016-09-07 16:15:53

标签: javascript reactjs

我制作了一个易于切换的组件,在这里我以一扇门为例。您单击门并打开,如果再次单击它,它将关闭。如果你点击门外,它也会关闭。

我的问题是,在handleClick()方法中,state.active总是false,无论如何。即使我设置了状态,它在我console.log时返回false。实际的door确实会分配给"active"类,那么为什么该方法看不到更改呢?

export default class Door extends React.Component {
  constructor() {
    super()
    this.state = {
      active: false,
    }

    this.close = this.close.bind(this)
    this.open = this.open.bind(this)
  }

  handleClick() {
    if (this.state.active == false) {
      this.open()
    } else {
      this.close()
    }
  }

  open() {
    document.body.addEventListener('click', this.close, true)
    this.setState({active: true})
  }

  close() {
    document.body.removeEventListener('click', this.close, true)
    this.setState({active: false})
  }

  render() {

    let classes = {
      active: this.state.active ? 'active ' : '',
    }

    return (
      <div onClick={this.handleClick.bind(this)} className={"door " + classes.active}>
      </div>
    )
  }
}

3 个答案:

答案 0 :(得分:3)

你应该停止传播:

handleClick(e) {
    e.stopPropagation();
    if (this.state.active == false) {
      this.open()
    } else {
      this.close()
    }
  }

当您尝试关闭门时,会调用handleClick两次。一旦通过div点击,然后通过身体点击。这可以通过在处理一次时阻止事件冒泡来避免。

答案 1 :(得分:0)

我认为您的混淆来自于尝试在handleClick中记录状态,在handleClick调用this.close()时,活动状态永远不会成立,始终< / em>发生在您的&#34;外部点击&#34;您在this.open中设置的事件处理程序。

  1. state.active start false false
  2. 用户点击门

    2a上。 active为false,请调用open()

    2B。使用下一次单击

  3. 添加将活动设置为false的事件侦听器
  4. 用户点击任意位置

    3A。在close()

    中,active设置为false

    3B。如果用户点击了门,GOTO 2,否则返回默认状态

  5. 通过代理setState方法,您可以看到活动状态实际上设置为true。

    &#13;
    &#13;
    class Door extends React.Component {
      constructor(props) {
        super(props)
        this.state = {
          active: false,
        }
        this.open = this.open.bind(this);
        this.close = this.close.bind(this);
      }
    
      setState(state) {
         console.log("Setting state: ", state);
         super.setState(state);
      }
    
      handleClick() {
        if (this.state.active == false) {
          this.open()
        } else {
          this.close()
        }
      }
    
      open() {
        this.setState({ active: true });
        document.body.addEventListener('click', this.close, true)
      }
    
      close(event) {
        this.setState({active: false});
        document.body.removeEventListener('click', this.close, true)
      }
    
      render() {
        let classes = {
          active: this.state.active ? 'active ' : '',
        }
    
        return (
          <div onClick={this.handleClick.bind(this)} className={"door " + classes.active}>
          </div>
        )
    }
    }
    
    ReactDOM.render(<Door />, document.querySelector('#app'));
    &#13;
    .door {
      height: 300px;
      width: 100px;
      background-color: brown;
    }
    
    .active {
      background-color: black;  
    }
    &#13;
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
        <div id="app"></div>
    &#13;
    &#13;
    &#13;

答案 2 :(得分:0)

我相信发生的事情是它打开,将状态设置为true,然后当你点击门关闭时,domEvent触发,触发close将状态设置为false,然后再次打开。

将您当前拥有的div放在另一个div中,并将该事件添加到div外部。

open() {
    var el = document.getElementById('outsideDiv');
    el.addEventListener('click', this.close, false)
    this.setState({active: true})
  }

  close() {
    var el = document.getElementById('outsideDiv');
    el.removeEventListener('click', this.close, false)
    this.setState({active: false})
  }

  render() {
    let classes = {
      active: this.state.active ? 'active ' : '',
    }

    return (
        <div id="outsideDiv">
          <div onClick={this.handleClick.bind(this)} className={"door " + classes.active}>
          </div>
      </div>
    )
  }
这样,当您点击门时,它不会记录点击。