0

I am trying to toggle class in one of my react component. At the beginning of the stage the element will be represented image and a hidden (disable) description. Whenever the user hover the element I want to add the class display only to the element hovered and not all the child components. In jquery usually I would have done $(this).addClass("display"), but in react I cannot figure it out.

I have seen many post and tutorial but could not find anything in regards. This is my code so far:

Parent component

import React, {Component} from 'react';
import ProjectItem from './ProjectItem';

let projects = [
  {
    name: 'Web Development Using PHP',
    techUsed : [
      'HTML5',
      'CSS3',
      'PHP'
    ],
    link : 'sample_link',
    img : 'asset/img/movie_catalog.png'
  },
  {
    name: 'Movie Catalog',
    techUsed : [
      'HTML5',
      'CSS3',
      'ReactJS',
      'JavaSript',
      'RESTAPI'
    ],
    link : 'sample_link',
    img : 'asset/img/fma_web.png'
  },
  {
    name: 'Web Development',
    techUsed : [
      'HTML5',
      'CSS3'
    ],
    link : 'sample_link',
    img : 'asset/img/fma_web.png'
  }
];

//Projects Component
export default class Projects extends Component{
  constructor(){
    super();
    this.state = {
      proj : projects
    }
  }

  //handle mouse enter 
  handleMouseEnter = () =>{
    this.setState({
      isHovered : true
    });
  }
  //handle mouse leave
  handleMouseLeave = () =>{
    this.setState({
      isHovered : false
    });
  }

  //render the component
  render(){


    return(
      <section className="projects">
        {/*section project wrapper*/}
        <div className="p-wrapper">
          <h1 className="title">Projects</h1>
          <hr/>
          {/*projet wrapper*/}
          <ProjectItem projects = {this.state.proj} /> 
        </div>
      </section>
    );
  }
}

Child component

import React, {Component} from 'react';

//export the component
export default class ProjectItem extends Component{
    constructor(){
        super();
        this.state = {
            isHovered : false
        }
    }
    //handle mouse enter 
    handleMouseEnter = () =>{
        this.setState({
            isHovered : true
        });
    }
    //handle mouse leave
    handleMouseLeave = () =>{
        this.setState({
            isHovered : false
        });
    }
    //render the project item component
    render(){
        let display = "";
        //assign the class based on the state of display
        if(this.state.isHovered === true){
            display = "active";
        }else{
            display = "disable";
        }

        return(
            <div className="projects-wrapper">
                {
                    this.props.projects.map((project, index) =>{
                        return(
                            <div className="project-item"  key={index} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave}>{/*FMA Web development*/}
                                <div className={"p-description " + display}>
                                <p>{project.name}</p>
                                <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Iure quos dolorem, ipsa eaque minima saepe fugit hic libero recusandae! Obcaecati esse odit id incidunt vitae aperiam dicta atque blanditiis sint?</p>
                                </div>
                                <div className="p-image">
                                <img src="asset/img/fma_web.png" alt="FMA Web Development"/>
                                </div>
                            </div>
                        )
                    })
                }
            </div>
        );
    }
} 

CSS

/*Projects Start*/
.projects{
  width: 100%;
}

.p-wrapper{
  margin: 0 auto;
  width: 90%;
  height: 100%;
}
.projects-wrapper{
  margin-top: 2rem;
  width: 100%;
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
}
.project-item{
  margin: 1rem;
  width: 30%;
  position: relative;
  box-shadow: 2px 3px 37px -5px rgba(0,0,0,0.84);
}
.p-description{
  position: absolute;
  height: 100%;
  width: 100%;
  background-color: rgba(43, 40, 40, 0.61);
  color: white;
}
.p-description p {
  margin: 1rem;
}
.p-title{
  margin: 1rem;
}
.active{
  display: block;
  transition: all 2s ease-in;
}
.disable {
  display: none;
}

Image-Illustration of the issue. enter image description here

I might be against the rules of the forum as I have already asked the question over here: LINK, However I have not gotten any concrete answer. Therefore, I am asking again.

2 Answers 2

1

The problem is that the local state of ProjectItem is applied to each project in this.props.projects.map. I would suggest instead mapping the projects in the Projects parent component instead, like this:

this.state.proj.map((proj, index) => {
  return <ProjectItem project = {proj} /> 
}

and then refactoring your ProjectItem component. Hope this helps!

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

Comments

0

Let container be the class you wish toggle when hover

return(    
    <div className={"row" + (this.state.hover?"container":"")} onMouseEnter={this.toggleHover} onMouseLeave={this.toggleHover} style={{borderStyle:'solid',borderWidth:'0.3px',padding:'5px 0 0 0'}}>
        something
        </div>)

and create function which will change the state when mouse enter and leave

toggleHover(e){
        console.log("is hovering")
        this.setState({"hover":!this.state.hover})
    }

and

constructor(props){
        super(props)

        this.state = {
            hover:false
        }
        this.toggleHover = this.toggleHover.bind(this)
    }

hope this help. this is working on my pc let me know if you have some trouble

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.