Lucas Santos
Lucas Santos

Reputation: 1369

How can I change a specific component in React on an eventHandler

What i'm trying to do should be fairly simple but it seems I am not able to get reference to the specific component using this

So here I have my App.js

import React, { Component } from 'react';
import CoolBox from './coolBox.js';
import './App.css';

    class App extends Component {

      changeColor(){
        $(this).css('background','blue');
      }

      render() {
        return (
          <div className="App">
            <CoolBox changeColor={function(){ this.changeColor() }.bind(this)} />
            <CoolBox changeColor={function(){ this.changeColor() }.bind(this)} />
            <CoolBox changeColor={function(){ this.changeColor() }.bind(this)} />
          </div>
        );
      }
    }

    export default App;

And then here is CoolBox.js which is just a simple box with a background of red:

import React, { Component } from 'react';
import $ from 'jquery';

class CoolBox extends Component {

  render() {
    return (
      <div onClick={this.props.changeColor} className="box"></div>
    );
  }
}

export default CoolBox;

Which simply looks like this: enter image description here

Now what I am trying to achieve is when you click on any of the 3 boxes the background color will change just on that specific box that was clicked.

It seems I cannot use any jquery methods if $(this) cannot be referenced. So how can I achieve this simple function within React?

Upvotes: 0

Views: 68

Answers (2)

Sagiv b.g
Sagiv b.g

Reputation: 31024

You don't need jQuery for this. There are couple of way to reference components in the DOM and there are couple of patterns of such components(controlled and uncontrolled) you should read about it.
As for you solution, this is a simple solution just to get you start with.
On event handlers you can access the event as an argument. changeColor(e) as e is the object that holds the event information as well as the target (the div you clicked in your case).
So basically what you can do in App.js is this:

class App extends React.Component {
            constructor(props){
        super(props);
        this.changeColor = this.changeColor.bind(this);
      }
      changeColor(e){
        e.target.style.background = "blue";
      }

      render() {
        return (
          <div className="App">
            <CoolBox changeColor={this.changeColor} />
            <CoolBox changeColor={this.changeColor} />
            <CoolBox changeColor={this.changeColor} />
          </div>
        );
      }
    }  

Please note
As you can see i bind the handler in the constructor instead of in the render method. that way you only bind it once and not on each render call witch will create a new instance on each render. that is better for performance.

Upvotes: 2

rossipedia
rossipedia

Reputation: 59367

this in a React component does not refer to the DOM element, rather it refers to the Component instance, as the DOM of a given component can change in arbitrary ways as a result of changing state or props.

As mentioned by @Chris in the comments above, you shouldn't really be using jQuery with your React components, unless you have a really good reason, and you know what you're doing.

Instead, you should use Component state to declare what you want, and then reflect your component's state in your render() method.

Here's an example

class CoolBox extends React.Component {
  
  constructor(...args) {
    super(...args);
    this.state = {
      color: 'red'
    };
    
    this.changeColor = this.changeColor.bind(this);
  }
  
  changeColor() {
    this.setState({
      color: this.state.color === 'red' ? 'green' : 'red'
    });
  }
  
  render() {
    return <div 
      onClick={this.changeColor} 
      className="box"
      style={{backgroundColor: this.state.color}}
      ></div>
  }
}


class App extends React.Component {
  render() {
    return (
      <div>
        <CoolBox />
        <CoolBox />
        <CoolBox />
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById('app'));
.box {
  height: 100px;
  width: 100px;
  margin: 10px;
  display: inline-block;
}
<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>

Upvotes: 1

Related Questions