0

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?

2
  • Why are you defining the changeColor method in App? If you define it in Coolbox, you should just be able to use regular this. In general, mixing jQuery into React this way isn't recommended. If you want something like it, use React's ref feature. Commented May 13, 2017 at 21:36
  • You should avoid using jQuery to change the DOM in tandem with React. Commented May 13, 2017 at 21:37

2 Answers 2

2

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Completely forgot about e.target. Thank you so much for the answer. I'm choosing your answer because it's the closest to $(this). @rossipedia had an amazing solution as well which is definitely something that people should consider but for my situation I am going with your e.target answer. Thank you!
1

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>

2 Comments

Hey thank you so much for the reply, really appreciate that! Your solution is what I had initially thought about but I wanted to avoid having the style within the component if possible because I am writing everything in SASS and there will be tons of style changes so it keeps things cleaner. As mentioned in the answer above by @Sag1v I can use e.target to target the element on the event which is probably the closest solution to replicate $(this). So for that reason I am choosing his answer but your answer is still amazing and can help many others as well. So +1, thank you!
No worries, glad you were able to get your problem solved!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.