2016-09-07 11 views
0

簡単に切り替え可能なコンポーネントを作っています。ここでは例としてドアを作っています。あなたはドアをクリックして開き、もう一度クリックすると閉じます。ドアの外側をクリックすると、ドアも閉じます。ここthis.setState()はバインドされたイベントで正しく動作しません

私の問題はhandleClick()方法では、state.activeはどんな、常にfalseではないということです。状態を設定した後でさえ、私はconsole.logそれを返します。実際の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> 
    ) 
    } 
} 
+0

私はコンテナが問題を抱えていると思っています。それは基本的にDoorコンポーネントをリセットするものです。コンテナからコードを共有できますか? –

+0

@JeffSiverそれはdivです。私は状態が変更されることを明確にすべきですが、 'handleClick'は変更を見ません。 –

+0

私は、このコンポーネントのReact Containerが新しいコンポーネントを作成しているため、状態がリセットされている可能性があります。それはあなたが見ている行動を説明するでしょう。だからこそ、Reactコンポーネントを含むコードを共有できるかどうかを尋ねました(私は明確ではありませんでしたが、残念です)。 –

答えて

3

あなたは伝播を停止する必要があります。

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

あなたがドアを閉めるしようとしているときは、handleClickが2回呼び出され。 divをクリックしてからbody clickをクリックします。これは、一度処理したときにイベントがバブリングするのを止めることで回避できます。

+0

私はこれを試しましたが、うまくいかなかった。しかし確かに、それは起こっていることです。 –

+0

更新:openメソッドとcloseメソッドにstopPropagationを追加すると修正されました。 –

0

私はあなたの混乱が​​の状態をログに記録しようとしてから来ていると思いますが、アクティブ状態はは常にあなたの「外をクリックし、」イベントハンドラあなたに起こることを、this.close()を呼び出す​​に真になるだろうことはありませんthis.openに設定します。

  1. state.activeがオフに始まり偽
  2. ユーザーがドア

    2Aをクリックします。アクティブな場合はfalseです。open()

    2bです。次のクリックでfalseに設定し、アクティブ

  3. ユーザーがどこでも

    3Aをクリックするイベントリスナーを追加します。 activeはfalseに設定されています。close()

    3bです。ユーザーがドアをクリックした場合、GOTO 2は、そうでない状態

をデフォルトに戻すあなたは、アクティブな状態が実際にsetState方法をプロキシでtrueに設定されていることがわかります。

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'));
.door { 
 
    height: 300px; 
 
    width: 100px; 
 
    background-color: brown; 
 
} 
 

 
.active { 
 
    background-color: black; 
 
}
<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>

0

私は何が起こっているのかと信じて、それが開いて当たることで、真の状態を設定し、あなたが閉じるためにドアのためにクリックすると、その後、domEvent火災は、状態を設定している近くのトリガ偽にしてから、もう一度開いてしまいます。

あなたが現在持っている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> 
    ) 
    } 

この方法では、ドアをクリックしたときにクリックが登録されません。

関連する問題