2017-06-02 6 views
1

キーボードの変更をマウスのクリックによる変更とは異なる方法で処理したい。この目的のために私は以下のコンポーネントを作成しました。私の問題は、ラジオボタンを選択するために矢印キーとスペースを使用すると、input要素からonChangeメソッドを使用する前に、親div要素のonClickメソッドを使用するということです。この動作の理由は何ですか?どうすれば正しく処理できますか?親要素のonClick onラジオボタンonChangeに反応する

class Radio extends React.Component { 
 
    constructor(props) { 
 
    super(props); 
 

 
    this.onChange = this.onChange.bind(this); 
 
    this.onClick = this.onClick.bind(this); 
 

 
    this.state = { checked: false }; 
 
    } 
 

 
    onChange() { 
 
    this.setState({ checked: !this.state.checked }); 
 
    console.log('onChange'); 
 
    } 
 

 
    onClick() { 
 
    this.onChange(); 
 
    console.log('onClick'); 
 
    } 
 

 
    render() { 
 
    return (
 
     <div onClick={this.onClick}> 
 
     <input 
 
      type="radio" 
 
      checked={this.state.checked} 
 
      onChange={this.onChange} 
 
     /> 
 
     Click me! 
 
     </div> 
 
    ); 
 
    } 
 
} 
 

 
ReactDOM.render(<Radio />, document.getElementById('root'));
<div id="root"></div> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.2/react.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.2/react-dom.min.js"></script>

答えて

2

W3C documentationのこの部分を、これがデフォルトのブラウザの動作のようです。

ユーザーがそれをクリックする以外の方法で定義されたアクティベーション動作を持つ要素をトリガすると、インタラクションイベントのデフォルトのアクションは、要素の上に合成クリックアクティベーションの手順を実行しなければなりません。これを回避するには

は、あなたのonClickハンドラで次のロジックを追加します。

if (e.type === 'click' && e.clientX !== 0 && e.clientY !== 0) { 
    // This is a real click. Do something here 
} 

credsをGitHubのユーザーRo Savageに、このことを指摘するために。


ここにあなたのための完全なデモです:

class Radio extends React.Component { 
 
    constructor(props) { 
 
    super(props); 
 

 
    this.onChange = this.onChange.bind(this); 
 
    this.onClick = this.onClick.bind(this); 
 

 
    this.state = { checked: false }; 
 
    } 
 

 
    onChange() { 
 
    this.setState({ checked: !this.state.checked }); 
 
    console.log('onChange'); 
 
    } 
 

 
    onClick(e) { 
 
    if (e.type === 'click' && e.clientX !== 0 && e.clientY !== 0) { 
 
     this.onChange(); 
 
     console.log('onClick'); 
 
    } else { 
 
     console.log('prevented "onClick" on keypress'); 
 
    } 
 
    } 
 

 
    render() { 
 
    return (
 
     <div onClick={this.onClick}> 
 
     <input 
 
      type="radio" 
 
      checked={this.state.checked} 
 
      onChange={this.onChange} 
 
     /> 
 
     Click me! 
 
     </div> 
 
    ); 
 
    } 
 
} 
 

 
ReactDOM.render(<Radio />, document.getElementById('root'));
<div id="root"></div> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.2/react.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.2/react-dom.min.js"></script>

+1

非常に興味深い!あなたのソリューションはうまくいく、ありがとう。 –

0

あなたは、クリックイベントの伝播無効にすることができます。this issueに見られるように

<input 
    type="radio" 
    checked={this.state.checked} 
    onClick={(e)=>{e.stopPropagation()}} 
    onChange={this.onChange} 
/> 
+0

あなたの答えをいただき、ありがとうございます。このソリューションの問題点は、キーボードを使用しているときにラジオボタンが視覚的にチェックされないことです。これを処理するオプションはありますか? –

0

は、イベントの順序が重要:クリックイベントが変更イベントの前に発生します。 は、イベントのバブルアップしているので、親要素のonClick -handlerは、子要素のonChange -handler前にトリガされます。あなたの特定の問題を解決するには

、あなたは、例えば、コンテナのdivの​​-eventを聞くことができました。このイベントは、クリックイベントまたは変更イベントの前にトリガーされる必要があります。

class Radio extends React.Component { 
 
    constructor(props) { 
 
    super(props); 
 

 
    this.onChange = this.onChange.bind(this); 
 
    this.onKeyUp = this.onKeyUp.bind(this); 
 

 
    this.state = { checked: false }; 
 
    } 
 

 
    onChange() { 
 
    this.setState({ checked: !this.state.checked }); 
 
    console.log('onChange'); 
 
    } 
 

 
    onKeyUp() { 
 
    console.log('onKeyUp'); 
 
    this.onChange(); 
 
    } 
 

 
    render() { 
 
    return (
 
     <div onKeyUp={this.onKeyUp}> 
 
     <input 
 
      type="radio" 
 
      checked={this.state.checked} 
 
      onChange={this.onChange} 
 
     /> 
 
     Click me! 
 
     </div> 
 
    ); 
 
    } 
 
} 
 

 
ReactDOM.render(<Radio />, document.getElementById('root'));
<div id="root"></div> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.2/react.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.2/react-dom.min.js"></script>

関連する問題