OnClick show one image, onClick show other image

Viewed 169

I am trying to make a mute and unmute function. But I'm not sure how to display an image path through an if statement. Currently it is just a button with text that switches back and forth on click.

  mute() {
const video = this.refs.video;
const muteButton = this.refs.mute;

if (video.muted === false) {
  video.muted = true;
  muteButton.innerHTML = "Unmute"; // this should be where the image is linked
} else {
  video.muted = false;
  muteButton.innerHTML = "Mute"; // this should be where the image is linked
}

}

<Button ref="mute" onClick={() => this.mute()} color="danger">
     Unmute
</Button>
4 Answers

You can use the ternary operator.

const muteButton = this.refs.mute;

<Button ref="mute" onClick={() => this.mute()} color="danger">
     { video.muted ? muteButton.innerHTML = "Unmute" : muteButton.innerHTML = "Mute" }
</Button>

Since you're using React, you shouldn't use innerHTML for such things. Just use ternary operator for that right in your JSX:

<Button ref="mute" onClick={() => this.mute()} color="danger">
     { video.muted ? 'Unmute' : 'Mute' }
</Button>

The same thing with image. You can put specific url directly:

<img src={ video.muted ? mutedUrl : unmutedUrl } />

Or you CSS class for that:

<Button className={ video.muted ? 'muted' : 'unmuted' } ...>
  ...
</Button>

Also, as i can see video is an element as well. It would be better to hold state in this.state.

toggle() {
  const { muted } = this.state;

  this.setState({ muted: !muted });
}

render() {
  const { muted } = this.state;

  ...
    <Video muted={ muted } ...>
      ...
    </Video>
    ...
    <Button ...>
      { muted ? 'Unmute' : 'Mute' }
    </Button>
  ...
}

You can improve your code a bit more by binding toggle() function:

// this option is better
toggle = () => {
  ...
};

// or in your constructor add
constructor(props) {
  ...

  this.toggle = this.toggle.bind();
}

Then you will be able to get rid of new anonymous function on each render:

<Button onClick={ this.toggle } ...>
  ...
</Button>

What you can do keeping a distinction between javascript logic and graphic is to create two css classes:

.mute{
   background: //your image with its style
}
.unmute{
  background: //same as above
}

and then in the javascript:

  function mute() {
     const video = this.refs.video;
     const muteButton = this.refs.mute;

     if (video.muted === false) {
        video.muted = true;
        muteButton.classList.remove("unmute");
        muteButton.classList.add("mute");
     } else {
        video.muted = false;
        muteButton.classList.remove("mute");
        muteButton.classList.add("unmute");
     }

You need to track your current state via react's state. Please see this sandbox.

Related