52

I am quite new to React and I am struggling a little with converting my thinking from standard js.

In my react component I have the following element:

<div className='base-state' onClick={this.handleClick}>click here</div>

The behaviour I am looking for is to add an extra class on click. My first idea was to try and add the class in the click handler function e.g.

handleClick : function(e) {
   <add class "click-state" here>
}

I haven't been able to find any examples that do anything similar though, so I am fairly sure I am not thinking about this in the right way.

Can anyone point me in the right direction?

6 Answers 6

61

The list of classes can be derive from the state of the component. For example:

var Component = React.createClass({
  getInitialState: function() {
    return {
      clicked: false
    };
  },

  handleClick: function() {
    this.setState({clicked: true});
  },

  render: function() {
    var className = this.state.clicked ? 'click-state' : 'base-state';
    return <div className={className} onClick={this.handleClick}>click here</div>;
  }
});

Calling this.setState will trigger a rerender of the component.

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

4 Comments

You can also use the classSet() addon helper: facebook.github.io/react/docs/class-name-manipulation.html
Im having a list of elements, when I implement this in my solution, the class changes for all the elements in the list. I want it to change only the one item from the list, the one item where I have clicked. Any solution to this?
For Temp O'rary person: For a list of elements, probably you haven't bound the click handler. Either in the element with something like onClick={() => this.handleClick} or in your constructor: this.handleClick = this.handleClick.bind(this); and in your handleClick, make the state be for the specific element (this.setState({someName}), for example), not just generic clicked: true
@TempO'rary in your click handler set some state which is the id or index of the clicked item, then in render, render the alternate class if the current item is the clicked item.
35

You could use just a Vanilla JS (event.target and classList):

handleClick = event => event.target.classList.add('click-state');

render() {
  return <div className="base-state" onClick={this.handleClick}>Click here</div>;
}

BUT don't do that!

React should handle changes in the DOM, so rely on modifying CSS classes via React.

Event.target

Element.classList

React / Styling and CSS

3 Comments

This is a great response when you want to change one element out of many. Thanks!
if target re-rendered then this class is no longer there!
This is an anti-pattern in React, please avoid doing this.
7

You could set click state in the click handler function and use it to set the class name conditionally using a template literal.

If you're using a function component, you can do it this way using the useState hook:

const [clicked, setClicked] = useState(false);

<div className={ `base-state ${clicked && 'click-state'}` } onClick={ () => setClicked(true) }>click here</div>

Comments

3

Every above solution is about setting className='click-state' on click but not removing class if already exist on double click. If someone is using a functional component, this behaviour can be achieved by using useState hook and some conditional statement.

const [clicked, setClicked] = useState('');

const handleClick = () => {
  clicked ? setClicked('') : setClicked('base-state click-state');
};

<div className={clicked || 'base-state' } onClick={handleClick}>click here</div>

Comments

1

Well to do this you can use Vanilla javascript but that might not be standard practice in react.

So what you can do is here:

let className = 'base-state';
  if (this.props.isActive) {
    className += ' click-state';
  }
  return <span className={className}>Menu</span>
}

to make it easier you can use an npm package called classnames

You can visit Npm package through this link.
for more references, you can visit the official React-docs

Comments

0

...

const [ classState, setClassState ] = useState('baseState')

    const onChange = (e) => {
        // You can use e.target to test calling element in case 
        //you need to use classState in more than one element
        //console.log(e.target)

        //if (e.target.name === 'name') {...

            setClassState('newClassState')

        // You can set to another state or back to baseState,
        // for multiple elements
        //else setClassState('baseState')
        // or 
        // else setClassState('anotherClassState')
    }

...

// I used name attribute in case you want to
// use the same state for another element.
// as stated above
<div className={classState === 'newClassState' ? newClassState : 'base-state'} onClick={e => handleClick(e)} name="name">click here</div>

// for another element
<div className={classState === 'anotherClassState' ? anotherClassState : 'base-state'} onClick={e => handleClick(e)} name="anotherName">click here instead</div>

Using classnames npm package might be what you need as stated in the comments.

Comments

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.