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>s를 루프 에 넣고 싶을 때 li.onli.off스타일을 background-color.


React의 수동 DOM 조작은 더 많은 문제를 일으킬 수 있는 안티 패턴 입니다. 같은 것을 피하십시오event.currentTarget.style.backgroundColor = '#ccc';수행중인 작업을 실제로 이해하지 않는 한 (대부분의 경우 타사 위젯을 통합하는 동안) .
Emile Bergeron

61

내가 생각할 수있는 두 가지 방법은

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
구성 요소가 렌더링 될 때마다 바인드를 수행하므로 렌더링 함수 내에서 바인드를 적용하지 않는 것이 좋습니다. 수명주기가 시작될 때 실행되는 일부 기능으로 이동할 수 있습니다.
jony89

1
@ jony89는 .bind추가 매개 변수를 사용하지 않으면 동의했습니다 . 그러나 첫 번째 경우에는 그렇습니다. 나는 또 다른 방법이라고 생각하지 않습니다
Dhiraj

1
세 가지 다른 함수를 생성합니다 (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이것은 큰 문제가 아닙니다. 클릭 가능한 항목이있는 생성 된 목록의 경우 이것은 매우 빠르게 큰 문제가됩니다. 이것이 특별히 경고를받은 이유입니다.
hippietrail

18

ECMA2015를 사용하십시오. 화살표 기능은 "this"를 훨씬 더 직관적으로 만듭니다.

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

@northamerican - 아니, 그것은 몇 가지 매개 변수 선명도를 추가하는 단지 거기
itcropper

5
이것은 실제로 렌더링 할 때마다 새로운 기능을 생성하므로 성능에 좋지 않습니다. 참조 : stackoverflow.com/questions/36677733/...
Jochie Nabuurs

1
필요하지 않은 경우 React 내에서 jQuery를 사용하지 마십시오!
Emile Bergeron

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

와 이벤트 처리 요소에 반응하는 DOM 요소의 이벤트를 처리하는 매우 유사하다. 몇 가지 구문 차이가 있습니다.

  • React 이벤트는 소문자가 아닌 camelCase를 사용하여 이름이 지정됩니다.
  • JSX를 사용하면 문자열이 아닌 이벤트 핸들러로 함수를 전달합니다.

그래서 React 에서 언급했듯이 문서 이벤트 처리에 관해서는 일반 HTML과 매우 유사하지만 camelcase를 사용하는 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 점 답변과 동일 해 보이며 예쁘거나 질문이있는 이유를 부활시킵니다.
Dave Newton

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>
    )
  }


복제는 완전히 불필요합니다.
Emile Bergeron

-17

이것은 JSX를 사용하지 않고 모든 것을 인라인으로 배치하는 비표준 (그렇게 드물지 않은) React 패턴입니다. 또한 Coffeescript입니다.

이를 수행하는 '반응 방식'은 구성 요소의 자체 상태입니다.

( 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는 내 화이트 보드 R & D 목적으로 만 로컬 이었지만이를 위해 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

12
어떤 식으로도 언급하지 않는 질문에 대한 답변에 CoffeeScript를 사용하는 이유는 무엇입니까? 말이 안되며 CoffeeScript를 모르거나 좋아하지 않을 수 있기 때문에 질문자가 답을 읽기가 더 어려워 질 수 있습니다. 분명히 반대 투표.
macbem

7
아니요,하지만 언어 위에 구축 된 것이므로 절대적으로 표준이 아니며 설치 및 컴파일이 필요합니다. 그들의 프로젝트에 커피 스크립트를 사용하고 있는지 전혀 ZERO 힌트가있을 때 그것은 커피 스크립트에 답을 작성하는 진정으로 가난한 선택이었다
TheRealMrCrowley

4
Coffeescript는 js 위에있는 레이어 일뿐입니다 . FTFY.
machineghost
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.