React JS onClickイベントハンドラー


120

私が持っています

var TestApp = React.createClass({
      getComponent: function(){
          console.log(this.props);
      },
      render: function(){
        return(
             <div>
             <ul>
                <li onClick={this.getComponent}>Component 1</li>
             </ul>
             </div>
        );
      }
});
React.renderComponent(<TestApp />, document.body);

クリックしたリスト要素の背景に色を付けたいのですが。Reactでこれを行うにはどうすればよいですか?

何かのようなもの

$('li').on('click', function(){
    $(this).css({'background-color': '#ccc'});
});

回答:


95

何故なの:

onItemClick: function (event) {

    event.currentTarget.style.backgroundColor = '#ccc';

},

render: function() {
    return (
        <div>
            <ul>
                <li onClick={this.onItemClick}>Component 1</li>
            </ul>
        </div>
    );
}

そして、よりリアクタティブになりたい場合は、選択したアイテムを、それを含むReactコンポーネントの状態として設定し、その状態を参照して、内のアイテムの色を決定することができますrender

onItemClick: function (event) {

    this.setState({ selectedItem: event.currentTarget.dataset.id });
    //where 'id' =  whatever suffix you give the data-* li attribute
},

render: function() {
    return (
        <div>
            <ul>
                <li onClick={this.onItemClick} data-id="1" className={this.state.selectedItem == 1 ? "on" : "off"}>Component 1</li>
                <li onClick={this.onItemClick} data-id="2" className={this.state.selectedItem == 2 ? "on" : "off"}>Component 2</li>
                <li onClick={this.onItemClick} data-id="3" className={this.state.selectedItem == 3 ? "on" : "off"}>Component 3</li>
            </ul>
        </div>
    );
},

これら<li>のをループに入れたいので、li.onli.offスタイルでを設定する必要がありますbackground-color


Reactでの手動DOM操作は、より多くの問題を引き起こすだけのアンチパターンです。event.currentTarget.style.backgroundColor = '#ccc';あなたが何をしているのか本当に理解していない限り(ほとんどの場合、サードパーティのウィジェットを統合している間)のようなことは避けてください。
エミールベルジェロン

61

私が考えることができる2つの方法は

var TestApp = React.createClass({
    getComponent: function(index) {
        $(this.getDOMNode()).find('li:nth-child(' + index + ')').css({
            'background-color': '#ccc'
        });
    },
    render: function() {
        return (
            <div>
              <ul>
                <li onClick={this.getComponent.bind(this, 1)}>Component 1</li>
                <li onClick={this.getComponent.bind(this, 2)}>Component 2</li>
                <li onClick={this.getComponent.bind(this, 3)}>Component 3</li>
              </ul>
            </div>
        );
    }
});
React.renderComponent(<TestApp /> , document.getElementById('soln1'));

これは私の個人的なお気に入りです。

var ListItem = React.createClass({
    getInitialState: function() {
        return {
            isSelected: false
        };
    },
    handleClick: function() {
        this.setState({
            isSelected: true
        })
    },
    render: function() {
        var isSelected = this.state.isSelected;
        var style = {
            'background-color': ''
        };
        if (isSelected) {
            style = {
                'background-color': '#ccc'
            };
        }
        return (
            <li onClick={this.handleClick} style={style}>{this.props.content}</li>
        );
    }
});

var TestApp2 = React.createClass({
    getComponent: function(index) {
        $(this.getDOMNode()).find('li:nth-child(' + index + ')').css({
            'background-color': '#ccc'
        });
    },
    render: function() {
        return (
            <div>
             <ul>
              <ListItem content="Component 1" />
              <ListItem content="Component 2" />
              <ListItem content="Component 3" />
             </ul>
            </div>
        );
    }
});
React.renderComponent(<TestApp2 /> , document.getElementById('soln2'));

ここにデモがあります

これがお役に立てば幸いです。


8
コンポーネントがレンダリングされるたびに適用されるため、render関数内でバインドを適用することはお勧めしません。ライフサイクルの開始時に実行されるいくつかの関数に移動することができます
jony89

1
@ jony89は.bind、追加のパラメーターを使用しない場合に合意しました。しかし、最初のケースではそうです。別の方法があるとは思いません
Dhiraj

1
3つの異なる関数(getComponent.bind(this、1)の結果によって作成される)を作成しますが、その明確さは決定である可能性があります(20に対してではなく、2から3のコンポーネントに対して実行します-本当にパフォーマンスの問題でない限り)動的に作成するのは簡単です)。
jony89

38

es6構文を使用して、質問のタイトルに答えていたreact onClickイベントハンドラーを定義する方法を次に示します。

import React, { Component } from 'react';

export default class Test extends Component {
  handleClick(e) {
    e.preventDefault()
    console.log(e.target)
  }

  render() {
    return (
      <a href='#' onClick={e => this.handleClick(e)}>click me</a>
    )
  }
}

9
どちらbindも矢印の機能は内で使用すべきではないrender、彼らはたびに作成される新しい機能になるための方法。これはコンポーネントの状態を変更する効果があり、状態が変更されたコンポーネントは常に再レンダリングされます。シングルの場合、aこれは大したことではありません。クリック可能なアイテムを含む生成されたリストの場合、これはすぐに大きな問題になります。これが特に警告されている理由です。
ヒッピートレイル2017

18

ECMA2015を使用します。アロー関数は「これ」をより直感的にします。

import React from 'react';


class TestApp extends React.Component {
   getComponent(e, index) {
       $(e.target).css({
           'background-color': '#ccc'
       });
   }
   render() {
       return (
           <div>
             <ul>
               <li onClick={(e) => this.getComponent(e, 1)}>Component 1</li>
               <li onClick={(e) => this.getComponent(e, 2)}>Component 2</li>
               <li onClick={(e) => this.getComponent(e, 3)}>Component 3</li>
             </ul>
           </div>
       );
   }
});
React.renderComponent(<TestApp /> , document.getElementById('soln1'));`

2
indexここでは何もしませんか?
北米の

@northamerican-いいえ、パラメータを明確にするためだけにあります
itcropper

5
レンダリングごとに新しい関数が作成されるため、これは実際にはパフォーマンスに悪影響を及ぼします。参照:stackoverflow.com/questions/36677733/...
Jochie Nabuurs

1
また、必要がない場合は、React内でjQueryを使用しないでください。
エミールベルジェロン

13

ES6を使用している場合、簡単なコード例を以下に示します。

import React from 'wherever_react_is';

class TestApp extends React.Component {

  getComponent(event) {
      console.log('li item clicked!');
      event.currentTarget.style.backgroundColor = '#ccc';
  }

  render() {
    return(
       <div>
         <ul>
            <li onClick={this.getComponent.bind(this)}>Component 1</li>
         </ul>
       </div>
    );
  }
}

export default TestApp;

ES6クラス本体では、関数は 'function'キーワードを必要とせず、コンマで区切る必要はありません。必要に応じて=>構文も使用できます。

動的に作成された要素の例を次に示します。

import React from 'wherever_react_is';

class TestApp extends React.Component {

constructor(props) {
  super(props);

  this.state = {
    data: [
      {name: 'Name 1', id: 123},
      {name: 'Name 2', id: 456}
    ]
  }
}

  getComponent(event) {
      console.log('li item clicked!');
      event.currentTarget.style.backgroundColor = '#ccc';
  }

  render() {        
       <div>
         <ul>
         {this.state.data.map(d => {
           return(
              <li key={d.id} onClick={this.getComponent.bind(this)}>{d.name}</li>
           )}
         )}
         </ul>
       </div>
    );
  }
}

export default TestApp;

動的に作成された各要素には、一意の参照「キー」が必要です。

さらに、(イベントではなく)実際のデータオブジェクトをonClick関数に渡したい場合は、それをバインドに渡す必要があります。例えば:

新しいonClick関数:

getComponent(object) {
    console.log(object.name);
}

データオブジェクトを渡す:

{this.state.data.map(d => {
    return(
      <li key={d.id} onClick={this.getComponent.bind(this, d)}>{d.name}</li>
    )}
)}

私はliアイテムを動的に構築しようとしていますが、これは未定義になり、onClick関数がエラーをスローします。
着陸

1
.bind(this)を使用する必要がある同様の答えを見つけました。あなたがバインドを作るまでは無名関数の最後に、ここでこれは、ウィンドウを指して...
上陸


6

React要素でのイベントの処理は、DOM要素でのイベントの処理とよく似ています。構文の違いがいくつかあります:

  • Reactイベントは、小文字ではなくキャメルケースを使用して名前が付けられます。
  • JSXでは、文字列ではなく関数をイベントハンドラーとして渡します。

したがって、Reactのドキュメントで述べたように、イベント処理に関しては通常のHTMLに非常に似ていますが、キャメルケースを使用したReactのイベント名は実際にはHTMLではないためJavaScriptであり、関数呼び出しを渡すときに関数を渡しますHTMLの文字列形式では、それらは異なりますが、概念はかなり似ています...

以下の例を見て、イベントが関数に渡される方法に注意してください。

function ActionLink() {
  function handleClick(e) {
    e.preventDefault();
    console.log('The link was clicked.');
  }

  return (
    <a href="#" onClick={handleClick}>
      Click me
    </a>
  );
}

3

import React from 'react';

class MyComponent extends React.Component {

  getComponent(event) {
      event.target.style.backgroundColor = '#ccc';
      
      // or you can write
      //arguments[0].target.style.backgroundColor = '#ccc';
  }

  render() {
    return(
       <div>
         <ul>
            <li onClick={this.getComponent.bind(this)}>Component 1</li>
         </ul>
       </div>
    );
  }
}

export { MyComponent };  // use this to be possible in future imports with {} like: import {MyComponent} from './MyComponent'
export default MyComponent;


これは基本的に11ポイントの回答と同じであり、かなりまたは疑問を呼び起こします。なぜですか?
デイブニュートン

2

class FrontendSkillList extends React.Component {
  constructor() {
    super();
    this.state = { selectedSkill: {} };
  }
  render() {
    return (
      <ul>
        {this.props.skills.map((skill, i) => (
            <li
              className={
                this.state.selectedSkill.id === skill.id ? "selected" : ""
              }
              onClick={this.selectSkill.bind(this, skill)}
              style={{ cursor: "pointer" }}
              key={skill.id}
            >
            {skill.name}
            </li>
        ))}
      </ul>
    );
  }

  selectSkill(selected) {
    if (selected.id !== this.state.selectedSkill.id) {
      this.setState({ selectedSkill: selected });
    } else {
      this.setState({ selectedSkill: {} });
    }
  }
}

const data = [
  { id: "1", name: "HTML5" },
  { id: "2", name: "CSS3" },
  { id: "3", name: "ES6 & ES7" }
];
const element = (
  <div>
    <h1>Frontend Skill List</h1>
    <FrontendSkillList skills={data} />
  </div>
);
ReactDOM.render(element, document.getElementById("root"));
.selected {
  background-color: rgba(217, 83, 79, 0.8);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id="root"></div>

@ user544079このデモがお役に立てば幸いです:)クラス名を切り替えて背景色を変更することをお勧めします。


2

import React from 'react';

class MyComponent extends React.Component {

  getComponent(event) {
      event.target.style.backgroundColor = '#ccc';
      
      // or you can write
      //arguments[0].target.style.backgroundColor = '#ccc';
  }

  render() {
    return(
       <div>
         <ul>
            <li onClick={this.getComponent.bind(this)}>Component 1</li>
         </ul>
       </div>
    );
  }
}

export { MyComponent };  // use this to be possible in future imports with {} like: import {MyComponent} from './MyComponent'
export default MyComponent;


これが問題をどのように修正できるかを説明することで、このコードにさらに多くのコンテキストを提供できますか?
MEDZ

1

React.createCloneメソッドを使用できます。要素のクローンを作成するよりも、要素を作成します。クローンの作成中に、小道具を注入できます。このようなonClick:メソッドプロップを挿入します

{ onClick : () => this.changeColor(originalElement, index) }

changeColorメソッドは複製で状態を設定し、プロセスで色を設定できるようにします。

render()
  {
    return(
      <ul>

        {this.state.items.map((val, ind) => {
          let item = <li key={ind}>{val}</li>;
          let props = { 
            onClick: () => this.Click(item, ind),
            key : ind,
            ind
          }
          let clone = React.cloneElement(item, props, [val]);
          return clone;
        })}

      </ul>
    )
  }


クローニングは完全に不要です。
エミールベルジェロン

-17

これは非標準です(それほど珍しくはありません)ReactパターンはJSXを使用せず、代わりにすべてをインラインにします。また、Coffeescriptです。

これを行う「React-way」は、コンポーネント自体の状態になります。

c = console.log.bind console

mock_items: [
    {
        name: 'item_a'
        uid: shortid()
    }
    {
        name: 'item_b'
        uid: shortid()
    }
    {
        name: 'item_c'
        uid: shortid()
    }
]
getInitialState: ->
    lighted_item: null
render: ->
    div null,
        ul null,
            for item, idx in @mock_items
                uid = item.uid
                li
                    key: uid
                    onClick: do (idx, uid) =>
                        (e) =>
                            # justf to illustrate these are bound in closure by the do lambda,
                            c idx
                            c uid
                            @setState
                                lighted_item: uid
                    style:
                        cursor: 'pointer'
                        background: do (uid) =>
                            c @state.lighted_item
                            c 'and uid', uid
                            if @state.lighted_item is uid then 'magenta' else 'chartreuse'
                        # background: 'chartreuse'
                    item.name

この例は機能します-ローカルでテストしました。このサンプルコードは、私のgithubで正確に確認できます。もともと、envは私自身のホワイトボードの研究開発目的でのみローカルでしたが、これをGithubに投稿しました。いつか上書きされるかもしれませんが、2016年9月8日からのコミットをチェックしてこれを確認できます。

より一般的には、ReactのこのCS / no-JSXパターンがどのように機能するかを確認したい場合は、こちらの最近の作業を確認してください。NodeJS、Primus、Redis、およびReactが含まれるスタックには、このアプリのアイデアのPOCを完全に実装する時間がある可能性があります。


背景が必要ではないdo:ラムダ:この表現も動作しますbackground: if @state.lighted_item is uid then 'magenta' else 'chartreuse'
ワイリークーリック

こんにちは、ブラウザコンソールでonclickを表示するにはどうすればよいですか?
Muneem Habib 2016

12
CoffeeScriptを、それについてまったく言及していない質問への回答に使用する理由は何ですか。それは意味をなさず、CoffeeScriptを知らない/好きではない可能性があるため、質問者にとって解答が読みにくくなる可能性があります。明らかに、反対投票。
macbem 2017年

7
いいえ、それは言語の上に構築されたものであり、完全に標準ではなく、インストールとコンパイルが必要です。彼らがプロジェクトで
コーヒースクリプト

4
Coffeescriptはjsの上のレイヤーにすぎません。FTFY。
machineghost
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.