Rakshith Jk
Rakshith Jk

Reputation: 151

How to assign variable id or classname to a div in ReactJS

I am developing a rating system using ReactJS.

my code is as follows - This is the essential code in my ReviewCard Component.
This basically returns a div where the review, username,and rating would be displayed.

starfunc(){
document.querySelector('.stars-inner').style.width = starPercentageRounded;
}

render(){
<h1 className="rating">Rating : {review.Rating}
            <div class="stars-outer">
               <div class="stars-inner" ></div>
              </div>
            </h1>
}

This is my Reviews Component It recieves reviews from DB, and for each review, maps in to ReviewCard Component

const reviewColumns = reviews ? reviews.map(review => (

        <ReviewCard review={review} styles={{backgroundColor:"black"},{padding:"5px"}} />

    )) : null;

The issue is that in my ReviewCard, the document.querySelector('.stars-inner') always takes the first instance of occurence. This is resulting in the only first review getting changed everytime.

Is there a way to keep the id or classname variable or unique? Or are there any other approaches i should follow?

Here is the full code

ReviewCard

class ReviewCardComponent extends React.Component {
  constructor(props) {
    super(props);


  }

  componentDidMount(){
    this.starfunc();
  }

  starfunc() {
    var {review} = this.props;
    var rating = review.Rating
    if(rating>5){
      rating = rating/2;
    }
    al = 5;

  const starPercentage = (rating / starTotal) * 100;
  const starPercentageRounded = `${(Math.round(starPercentage / 10) * 10)}%`;
  document.querySelector(id).style.width = starPercentageRounded; 
  }


  render() {
    console.log("reviewcard",this.props);

    const {review} = this.props;
    // The CardTitle.subtitle won't render if it's null

    console.log("qwer",review.review_id);
    return (


      <div className="main">
        <div className="fline">

          <h1 className="name">{review.user_name}</h1> 


          <h1 className="rating">Rating : {review.Rating}
            <div class="stars-outer">
               <div class="stars-inner" id={review.user_name}></div>
              </div>
            </h1>

          <button className="DeleteOptions">Options</button>

        </div>

        <h2 className="reviewtext">{review.review}</h2>
        <hr/>
      </div>



    );
  }
}

its CSS file

.stars-outer {
    display: inline-block;
    position: relative;
    font-family: FontAwesome;
  }

  .stars-outer::before {
    content: "\f006 \f006 \f006 \f006 \f006";
  }

  .stars-inner {
    position: absolute;
    top: 0;
    left: 0;
    white-space: nowrap;
    overflow: hidden;
    width: 0;
  }

  .stars-inner::before {
    content: "\f005 \f005 \f005 \f005 \f005";
    color: #f8ce0b;
  }

Upvotes: 1

Views: 2858

Answers (2)

Tzvetan Marinov
Tzvetan Marinov

Reputation: 26

Your approach is wrong :) You should not use querySelector as this accesses the real DOM element and not the React virtualDOM element; The approach is to use the React Refs system :

  1. In your ReviewCard Component in the constructor put this.review = React.createRef();
  2. In the div with class "stars-inner" put ref={this.review} as a prop;
  3. In your componentDidMount() life cycle method use this.review.current.style.width to set your styles

PS: Where is your return for the JSX inside the render() for your ReviewCard Component ?

Upvotes: 1

Duc Hong
Duc Hong

Reputation: 1179

In your case, I think the <Review /> component would look like this:

  • Please note that I've changed your starfunc function to arrow function to utilize this
  • Have a percentage state in each <Review /> component, by default it will be 0
class ReviewCardComponent extends React.Component {
  state = {
    percentage: 0,
  }

  componentDidMount() {
    this.starfunc();
  }

  starfunc = () => {
    const { review } = this.props;
    const rating = review.Rating;
    const starTotal = 5;

    if (rating > 5) {
      rating = rating / 2;
    }

    const starPercentage = (rating / starTotal) * 100;
    const starPercentageRounded = Math.round(starPercentage / 10) * 10;

    this.setState({
      percentage: starPercentageRounded || 0
    })
  }

  render() {
    const { review } = this.props;
    const { percentage } = this.state;
    // The CardTitle.subtitle won't render if it's null

    console.log("qwer", review.review_id);
    return (
      <div className="main">
        <div className="fline">
          <h1 className="name">{review.user_name}</h1>

          <h1 className="rating">
            Rating : {review.Rating}
            <div class="stars-outer">
              <div class="stars-inner" id={review.user_name} style={{width: `${percentage}%`}}></div>
            </div>
          </h1>

          <button className="DeleteOptions">Options</button>
        </div>

        <h2 className="reviewtext">{review.review}</h2>
        <hr />
      </div>
    );
  }
}

Upvotes: 2

Related Questions