Reputation: 40634
I want to change the css class of a span
element whenever an anchor is clicked
I will modify the css class in the onclick callback
class Button extends Component {
handleCallback() {
this.icon.className = this.icon.className + ' wiggle'
}
render() {
return (
<div>
<span className='highlight'>{this.props.summary}</span>
<a
className='link'
onClick={this.handleCallback}
>
<span ref={(c) => this.icon = c} className='icon-up'></span>
</a>
</div>
);
}
}
To do so I need to be able to refer the component. That's why I use the ref
attribute in the span class.
However when the callback is called, I got this error:
Uncaught TypeError: Cannot read property 'icon' of null
Why the ref
does not work here?
Upvotes: 1
Views: 5981
Reputation: 47172
You're missing a few things here
First off, you're writing an ES6 component class and when using ES6 together with React, React no longer features auto binding of this
making your call to handleCallback
refer to a this
which will be null.
this.handleCallback.bind(this)
or declare your callback with an arrow function handleCallback = () => {}
will take care of that problem.
And secondly, the way you're trying to set the className is not allowed, React only updates the tree (i.e., what you see) when re-rendering and React will never flush the changes you made 'inline' back into the DOM so you would have to utilize this.setState()
or this.forceUpdate()
in order to be able to see, but since your changes are inline they will never persist on a subsequent render.
Below is a very verbose Component to illustrate how to do it
class Button extends React.Component {
constructor() {
super();
this.state = {
shouldWiggle: false
};
}
handleCallback() {
this.setState({shouldWiggle: !this.state.shouldWiggle});
}
render() {
let cls = this.state.shouldWiggle ? 'icon-up wiggle': 'icon-up';
return (
<div>
<span className='highlight'>{this.props.summary}</span>
<a
className='link'
onClick={this.handleCallback.bind(this)}
>
<span ref={(c) => this.icon = c} className={cls}>ad</span>
</a>
</div>
);
}
}
Upvotes: 3