Home > Software engineering >  React: after load page state is true, although useState is false
React: after load page state is true, although useState is false

Time:07-09

In the application, by clicking on the button, I want to do 2 things: play an audio file, show 2 pictures. After clicking the button again, I want to turn off the audio and hide 2 pictures. The audio works, but the pictures go crazy. Why? I set useState as "false" in default, but after loading pages they are "true". I do not understand why?

import {useEffect, useRef, useState} from "react";

import styled from "./Cat.module.scss";
import Swing from "../../assets/audio/GirlsLikeToSwing.mp3";

let dancingImg = ['https://i.gifer.com/P6XV.gif', 'https://i.gifer.com/DCy.gif']

const Cat = () => {
    const [isPlaying, setIsPlaying] = useState(false);
    const audioElement = useRef();
    const [ladyDancing, setLadyDancing] = useState(false);
    const [catDancing, setCatDancing] = useState(false);

    const playPause = () => {
        setIsPlaying(!isPlaying);
    }

    useEffect(() => {
        if (isPlaying) {
            audioElement.current.play();
            setLadyDancing(ladyDancing);
            setCatDancing(catDancing);
        } else {
            audioElement.current.pause();
            setLadyDancing(!ladyDancing);
            setCatDancing(!catDancing);
        }
    }, [isPlaying]);

    return (<div className={styled.headerContainer}>
            <div className={styled.lady}>
                {ladyDancing ? <img src={dancingImg[0]} alt="" className={styled.ladyDancing}/> : null}
                {catDancing ? <img src={dancingImg[1]} alt="" className={styled.catDancing}/> : null}

            </div>

            <button onClick={playPause}>Play</button>
            

            <audio src={Swing} ref={audioElement}></audio>
        </div>

    )
};
      
export default Cat;

enter image description here

CodePudding user response:

useEffect runs during the first render and all subsequent updates.

I believe you might need to explicitly perform setLadyDancing to true or false depending on the state that you want them to be, otherwise it will keep getting toggled based on its previous state.

Maybe this might work:

useEffect(() => {
        if (isPlaying) {
            audioElement.current.play();
            setLadyDancing(true);
            setCatDancing(true);
        } else {
            audioElement.current.pause();
            setLadyDancing(false);
            setCatDancing(false);
        }
    }, [isPlaying]);

CodePudding user response:

Just use isPlaying state for images.

import { useEffect, useRef, useState } from 'react'

import styled from './Cat.module.scss'
import Swing from '../../assets/audio/GirlsLikeToSwing.mp3'

let dancingImg = ['https://i.gifer.com/P6XV.gif', 'https://i.gifer.com/DCy.gif']

const Cat = () => {
  const audioElement = useRef()
  const [isPlaying, setIsPlaying] = useState(false)

  const toggleAudio = () => {
    setIsPlaying((prevState) => !prevState)
  }

  return (
    <div className={styled.headerContainer}>
      <div className={styled.lady}>
        {isPlaying ? <img src={dancingImg[0]} alt="" className={styled.ladyDancing} /> : null}
        {isPlaying ? <img src={dancingImg[1]} alt="" className={styled.catDancing} /> : null}
      </div>

      <button onClick={toggleAudio}>Play</button>

      <audio src={Swing} ref={audioElement}></audio>
    </div>
  )
}

export default Cat

CodePudding user response:

The state is true when the page loads because on the initial render the useEffect block gets called and it's setting them to !ladyDancing and !catDancing which makes it true.

I recommend using a separate function for it (and remove useEffect).

And also about the pictures: you are setting them to their values when isPlaying is true. To fix that, you would need to set them to true (when playing) or false (when not playing).

The code:

const playPause = () => {
    setIsPlaying(!isPlaying);
    toggle(); // call the function
}

const toggle = () => { // the name of the function can be whatever you want
    if (isPlaying) {
        audioElement.current.play();
        setLadyDancing(true);
        setCatDancing(true);
    } else {
        audioElement.current.pause();
        setLadyDancing(false);
        setCatDancing(false);
    }
}
  • Related