Reputation: 2064
Still trying to learn React. I'm trying to show an image when you hover. This is my Item component.
import React from 'react';
import Eyecon from '../../static/eye.svg';
class Item extends React.Component {
constructor(props) {
super(props);
this.displayName = 'Item';
this.state = {
hover: false
};
}
mouseOver() {
this.setState({hover: true});
}
mouseOut() {
this.setState({hover: false});
}
render() {
const { item, i } = this.props;
return (
<div className="grid-box" onMouseOver={this.mouseOver} onMouseOut={this.mouseOut}>
{this.state.hover ? (<img src={Eyecon}/>) : null}
</div>
)
}
}
export default Item;
How would I make it so only the item I hover over shows the image?
Upvotes: 1
Views: 8868
Reputation: 6633
This is just a 'this' binding issue. Put a console.log inside of your mouseOver and mouseOut methods and you'll notice that your state isn't changing.
There are many ways to bind the 'this' context in your class methods. I'll show you three ways to do it in this example (DO NOT do all three methods, just choose one).
import React from 'react';
import Eyecon from '../../static/eye.svg';
class Item extends React.Component {
constructor(props) {
super(props);
this.displayName = 'Item';
// 1. bind your functions in the constructor.
this.mouseOver = this.mouseOver.bind(this);
this.mouseOut = this.mouseOut.bind(this);
this.state = {
hover: false
};
}
// 2. bind it with fat arrows.
mouseOver = () => {
this.setState({hover: true});
}
mouseOut() {
this.setState({hover: false});
}
render() {
const { item, i } = this.props;
// 3. bind them in the render method (not recommended for performance reasons)
return (
<div className="grid-box" onMouseOver={this.mouseOver.bind(this)} onMouseOut={this.mouseOut.bind(this)}>
{this.state.hover ? (<img src={Eyecon}/>) : null}
</div>
)
}
}
export default Item;
Here's an explanation of different ways to bind your 'this' context in react using ES6 classes: http://egorsmirnov.me/2015/08/16/react-and-es6-part3.html
Upvotes: 2
Reputation: 59491
The other solutions suggested are perfectly valid, however you can solve this easily by just converting your functions to ES6 arrow functions.
An arrow function expression has a shorter syntax compared to function expressions and lexically binds the this value (does not bind its own this, arguments, super, or new.target). Arrow functions are always anonymous.
Like so:
mouseOver = () => {
this.setState({hover: true});
}
mouseOut = () => {
this.setState({hover: false});
}
Simple.
Upvotes: 0
Reputation: 7258
Maybe it's because you have to bind mouseOver
and mouseOut
calls in order to use this.setState
inside them.
Replace:
<div className="grid-box" onMouseOver={this.mouseOver} onMouseOut={this.mouseOut}>
with:
<div className="grid-box" onMouseOver={this.mouseOver.bind(this)} onMouseOut={this.mouseOut.bind(this)}>
Upvotes: 0