How to get a React Component reference to change its class using classList?

25,216

Solution 1

As you have specified in your code that your class name is used using a state variable named 'class' containing the value 'tabBody tab activeTab'

className: this.state.class,

Thats why you must have to use setState() method to change your className. As you have the reference to your class instance in global namespace named 'Interface.tabBody' which can be used to set your className by calling setState() e.g

Interface.tabBody.setState({class: 'tabBody tab activeTab disabled'});

This method is used when you want to access class instance outside of the React.

if you are using handleclick() in your react then you can use the following code

handleTabClick = function() {
  this.setState({class: 'tabBody tab activeTab disabled'});
}

By calling setState() the React will detect changes and re-renders component.

Solution 2

Above 16.8, using useRef hooks for functional components,

// useRef takes initialValue as param
const fooBarRef = useRef(null);

//DOM Usage
<div className="foo" ref={fooBarRef}>Hello</div>

Usage of reference for useRef after mounting node element,

//Getting node element
const fooBarNode = fooBarRef.current

//Adding class to node element
fooBarNode.classList.add('bar');

Above 16.3, using createRef for class components,

// Creating ref in a constructor
this.fooBarRef = React.createRef();

// DOM usage
<div className="foo" ref={this.fooBarRef}>Hello</div>

Usage of reference for createRef after mounting node element,

//Getting node element
const fooBarNode = this.fooBarRef.current

//Adding class to node element
fooBarNode.classList.add('bar');

Below 16.3, using callBackRef,

// Creating ref in a constructor
this.fooBarRef = null;
this.setFooBarRef = (ref) => {
  this.fooBarRef = ref;
}

// DOM usage
<div className="foo" ref={this.setFooBarRef}>Hello</div>

Usage of reference after mounting node element,

//Adding class name
this.fooBarRef.classList.add('bar');

Solution 3

That's because this is the reference to your class instance, not a DOM element. To access DOM elements (since React uses a virtual DOM) you need to create a reference, i.e:

React.createElement('div', {
  ref: 'tabBody'

You can then access it via this.refs.tabBody

You shouldn't pass this reference outside of the class however. Instead you can pass the reference to handleTabClick when the event happens:

React.createElement('div', {
  ref: 'tabBody'
  onClick: e => this.props.handleTabClick(e, this.refs.tabBody)

Then you can do:

handleTabClick = function(e, tabBody) {
    tabBody.classList.add('tabPreviewComplete');
}

Personally I would change the state though, so that if the component re-renders it has the correct class.

Fiddle: http://jsfiddle.net/ferahl/dpvb1h3y/

Share:
25,216
Muhammad Asif Javed
Author by

Muhammad Asif Javed

I am software Engineer at CoutAllure.Ltd

Updated on July 09, 2022

Comments

  • Muhammad Asif Javed
    Muhammad Asif Javed almost 2 years

    I have create a React Component using the following code. In this i am creating tab and added the class and storing its reference to in a global namespace Interface for further processing.

    var TabBody = React.createClass({
      getInitialState: function() {
        return {
          class: 'tabBody tab activeTab'
        }
      },
      render: function() {
        Interfaces.tabBody = this;
        tabSelectionInfo.tabBody = this;
        return (
          React.createElement('div', {
              className: this.state.class,
              onClick: handleTabClick
            },
            React.createElement('span', {}, "Body"))
        );
      }
    });
    

    now using the following function, To add a class to the above component and console is showing an error undefined. how i store the refrance of this component in order to change its class later.

    handleTabClick = function() {
      Interfaces.tabBody.classList.add('tabPreviewComplete');
    }
    
  • Muhammad Asif Javed
    Muhammad Asif Javed over 8 years
    i think this is used just in the scope of object component but i am trying to use outside the elecment
  • Dominic
    Dominic over 8 years
    I can assure you that this works, you are probably trying to pass the reference out of your class which would be incorrect, I'll add something to help with that
  • Muhammad Asif Javed
    Muhammad Asif Javed over 8 years
    so will i have to write sepreate function for each class instead of genaric function
  • Muhammad Asif Javed
    Muhammad Asif Javed over 8 years
    what will happen if i want to use the refs of other component in this i.e tabBody.classList.add('tabPreviewComplete');tabNeck.classLis‌​t.remove('active');
  • Goran_Ilic_Ilke
    Goran_Ilic_Ilke over 2 years
    For me,on socket event in useEffect simply doesnt work.