2

I have a browser based game I am creating with React. The user will have lives that will decrease when a given event occurs. Lives are displayed to the player via 3 font-awesome heart icons. I am using react-fontawesome.

Getting the icons to display is not an issue. I am looking for a cleaner way to display the 3 heart icons based off state (trying not to use nested if statements or switch statement if possible).

// initial state

state = { lives: 3 }



// import of FA icon with react-fontawesome

import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'

import { faHeart } from '@fortawesome/free-solid-svg-icons'



// assigning icon to variable

let hearts = <FontAwesomeIcon icon={faHeart} className="mx-1" />;



// displaying icon

<div className="d-flex panel-content-md">{ hearts }</div>

When the state of 'lives' decreases, a heart icon should be removed indicating to the player they have loss a life. I have found to display multiple icons in the 'hearts' variable, you have to wrap the tags in a parent div tag:

let hearts = (
    <div>
        <FontAwesomeIcon icon={faHeart} className="mx-1" />
        <FontAwesomeIcon icon={faHeart} className="mx-1" />
        <FontAwesomeIcon icon={faHeart} className="mx-1" />
    </div>
)

I have not found a clean conditional rendering solution that just looks at the number that is assigned to 'lives' and updates the amount of hearts that are displayed. I have a feeling I am overlooking the obvious here.

biljohns
  • 33
  • 4

3 Answers3

3

You could to this by mapping an array of length equal to your state.lives value:

<div>
  {
     [...Array(this.state.lives).keys()].map(i => (
        <FontAwesomeIcon key={i} icon={faHeart} className="mx-1" />
     )
  }
</div>

Or just store your lives as an array or as a string of one character per life

// this.state.livesArray is [1,2,3]
<div>
  {
     this.state.livesArray.map(i => (
        <FontAwesomeIcon key={i} icon={faHeart} className="mx-1" />
     )
  }
</div>
// this.state.livesString is "❤❤❤"
<div>
  {
     this.state.livesString.split('').map(i => (
        <FontAwesomeIcon key={i} icon={faHeart} className="mx-1" />
     )
  }
</div>
giuseppedeponte
  • 2,366
  • 1
  • 9
  • 19
0

Or simply by conditional rendering

let heart = <FontAwesomeIcon icon={faHeart} className="mx-1" />;


<div className="d-flex panel-content-md">
  {this.state.lives >= 1 && heart }
  {this.state.lives >= 2 && heart }
  {this.state.lives >= 3 && heart } // or === 3 if you don't want to add extra lives in the future
</div>
0

A bit simpler Code,

render() {
  let hearts = [];

  for(let i=0; i<this.state.lives; i++) {
    hearts.push(<FontAwesomeIcon key={i} icon={faHeart} className="mx-1" />)
  }

  return(
    <div>{hearts}</div>
  );
}
Gangadhar Gandi
  • 2,162
  • 12
  • 19