RebeccaK375
RebeccaK375

Reputation: 901

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)

Upvotes: 4

Views: 15648

Answers (4)

therealak12
therealak12

Reputation: 1326

You can use Context and make a theme-like color set for your components. Read about the context in the docs and codeburst.

Upvotes: 0

djfdev
djfdev

Reputation: 6037

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)}
    />
  )
}

Upvotes: 4

Ryan Villanueva
Ryan Villanueva

Reputation: 116

In React, you generally pass properties down to children components. So rather than trying to "reach up and over" into an unrelated component to access it's state, you should be accessing a state that's been passed down to your from a shared parent component.

So if the ImageX component is a child of Product, you can pass the state directly into it <ImageX hover={this.state.hover} />. You can then access hover in the ImageX props.

If it's not a child of Product, you'll want to pass down the state from a shared parent and access it from both components.

Upvotes: 2

xDreamCoding
xDreamCoding

Reputation: 1694

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} />
   }
}

Upvotes: 4

Related Questions