Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React: on hover over component 1, change the style of another component

I am learning react and I have some code which waits for a hover over a button and then applies an opaque white overlay over the image over which you hover (and this works):

class Product extends Component {
  constructor(props) {
        super(props);
        // 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() {
    return (
      <Link to={"/products/"+this.props.value.uid}>
        <button className="Product" onMouseEnter={this.mouseOver.bind(this)} onMouseLeave={this.mouseOut.bind(this)}>
          <img className="ImageGrid" src={this.props.value.media}/>
          {this.state.hover ? (
            <div className="ImageOverlay"> 
              <div className="TextOverlay">
                <p><b>{this.props.value.name}</b></p>
                <p>${this.props.value.price}</p>
              </div>
            </div>) : null}  
        </button>
      </Link>
    );
  }
}

My question is... let's say that instead of adding an overlay over the image rendered by this component, I wanted to change an image rendered by another component and not by applying an overlay div, but by changing some CSS setting of said image, like applying a filter: filter: grayscale(100%). So there is this image:

<img className="PicBox" src={this.state.img[sid-1]} />

Rendered by another component.

Here is what I am thinking the strategy might be:

Have my original component (the one over which I hover), have a prop "state" which keeps track on whether or not i hover over it, like I did above.

In the other component which renders ImageX, I need to somehow access the prop of the Hover component, and check its state, to decide how to render the image (with grayscale or not).

How do I access state of the hover component within another component?

(Or if my strategy is off, a hint would be appreciated)

like image 355
RebeccaK375 Avatar asked Dec 24 '22 18:12

RebeccaK375


2 Answers

As long as you don't use some state managing library such as redux or flux and you want to access state between components, you need a common parent between those. In the end you have something like this (pseudocode):

ParentComponent {
   hoverHandler(isHover) {
       this.childIsHover = isHover;
   }
   render() {
        <hoverComponent onHover={this.hoverHandler} />
        <imageComponent overlay={this.childIsHover} />
   }
}
like image 106
xDreamCoding Avatar answered Dec 26 '22 06:12

xDreamCoding


When working with React, you've got to think about who should have the responsibility of maintaining state. So in this case, the state should not be stored in the button component, because it needs to be accessed by another component which is not one of its children.

Instead, you should create a parent component that is responsible for storing the hover state, and also renders both the button and image components. You can bind functions to the parent, so that when they are passed as props to other children, they can still update the state of the parent.

So for example, your parent component might look like this:

class Parent extends Component {
  constructor () {
    super()

    this.state = {
      hover: false
    }

    this.updateHoverState = this.updateHoverState.bind(this)
  }

  updateHoverState (hover) {
    this.setState({ hover: hover })
  }

  render () {
    <div>
      <ButtonComponent updateHoverState={this.updateHoverState} />
      <ImageComponent hover={this.state.hover} />
    </div>
  }
}

Now, your button component can just be a function, and does not need to maintain any state of its own. You can update the parent state by calling this.props.updateHoverState:

function ButtonComponent (props) {
  return (
    <button
      onMouseEnter={() => this.props.updateHoverState(true)}
      onMouseLeave={() => this.props.updateHoverState(false)}
    />
  )
}
like image 32
djfdev Avatar answered Dec 26 '22 08:12

djfdev