J'ai du mal à réussir à rétablir un état. Ce que j'essaie de réaliser, c'est que lorsque je clique sur un bouton de lecture (PlayContainer), je modifie le contenu à l'intérieur de {play}. Cette fonction fonctionne mais j'ai du mal à annuler la modification sur un autre clic {stop}. (J'utilise des composants stylisés afin que les éléments aient des noms définis.)

export default function Play() {

  const [play, setStatus] = useState(() => {
    return (
      <RadioContainer>
        <PlayButton src="/img/play.svg" />
      </RadioContainer>
    );
  });

  function start() {
    setStatus(() => {
      return (
        <RadioContainerSecond onClick={stop}>
          <PlayButton src="/img/pause.svg" />
          <Video
            width="560"
            height="315"
            src="https://www.youtube.com/embed/21qNxnCS8WU?autoplay=1&controls=0"
            title="YouTube video player"
            frameborder="0"
            allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
          />
        </RadioContainerSecond>
      );
    });
  }

  function stop() {
    setStatus(() => {
      return (
        <RadioContainer>
          <PlayButton src="/img/play.svg" />
        </RadioContainer>
      );
    });
  }

  return (
    <OuterCircle>
      <InnerCircle>
        <PlayContainer onClick={start}>{play}</PlayContainer>
      </InnerCircle>
    </OuterCircle>
  );
}

Peut-être que je me trompe, faites-moi savoir s'il existe des méthodes plus faciles ou meilleures.

1
Sigurdarson 3 oct. 2021 à 02:23

3 réponses

Meilleure réponse

Le stockage de JSX dans l'état React est généralement anti-modèle dans React. Vous devez stocker des données et afficher votre interface utilisateur à partir des données stockées dans state. Stocke une valeur booléenne dans state pour représenter l'état play/stop et rend conditionnellement un élément ou l'autre en fonction de l'état actuel.

export default function Play() {
  const [play, setStatus] = useState(false);

  function start() {
    setStatus(true);
  }

  function stop() {
    setStatus(false);
  }

  return (
    <OuterCircle>
      <InnerCircle>
        <PlayContainer onClick={start}>
          {play ? (
            <RadioContainerSecond onClick={stop}>
              <PlayButton src="/img/pause.svg" />
              <Video
                width="560"
                height="315"
                src="https://www.youtube.com/embed/21qNxnCS8WU?autoplay=1&controls=0"
                title="YouTube video player"
                frameborder="0"
                allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
              />
            </RadioContainerSecond>
          ) : (
            <RadioContainer>
              <PlayButton src="/img/play.svg" />
            </RadioContainer>
          )}
        </PlayContainer>
      </InnerCircle>
    </OuterCircle>
  );
}
0
Drew Reese 2 oct. 2021 à 23:53

Je pense qu'il est préférable d'utiliser un booléen pour play au lieu d'un composant. Vous pouvez ensuite basculer le composant en fonction du booléen play comme ceci :

export default function Play() {
    const [play, setPlay] = useState(false); // Boolean instead of component

    function start() {
      setPlay(true); // Simply toggle boolean
    }

    function stop() {
      setPlay(false); // Simply toggle boolean
    }

    return (
        <OuterCircle>
            <InnerCircle>
                <PlayContainer onClick={start}>
          {
          {/* Toggle between the 2 components based on the play boolean */}
          play
           {/* If play is true use RadioContainerSecond */}
            ? (<RadioContainerSecond onClick={stop}>
                <PlayButton src="/img/pause.svg" />
                <Video
                  width="560"
                  height="315"
                  src="https://www.youtube.com/embed/21qNxnCS8WU?autoplay=1&controls=0"
                  title="YouTube video player"
                  frameborder="0"
                  allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
                />
              </RadioContainerSecond>)
            {/* If play is false use RadioContainer */}
              : (<RadioContainer>
                  <PlayButton src="/img/play.svg" />
                </RadioContainer>)
        }
        </PlayContainer>
            </InnerCircle>
        </OuterCircle>
    );
}
0
justpen 2 oct. 2021 à 23:51

Il y a des problèmes dans ton code. Tout d'abord, vous stockez des éléments JSX dans un état qui est une mauvaise idée. Deuxièmement, ce composant a 2 instructions de retour (il devrait donner une erreur). Votre code peut être mis à jour à la place :

export default function Play() {

  const [play, setStatus] = useState(false)

  const mainComponent = !play 
      ? <RadioContainer>
          <PlayButton src="/img/play.svg" onClick={() => setState(true)}/>
        </RadioContainer>
      : <RadioContainerSecond>
          <PlayButton src="/img/pause.svg" onClick={() => setState(false)}/>
          <Video
            width="560"
            height="315"
            src="https://www.youtube.com/embed/21qNxnCS8WU?autoplay=1&controls=0"
            title="YouTube video player"
            frameborder="0"
            allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
          />
        </RadioContainerSecond>
    

  return (
    <OuterCircle>
      <InnerCircle>
        { mainComponent }
      </InnerCircle>
    </OuterCircle>
  );
}
0
ABDULLOKH MUKHAMMADJONOB 2 oct. 2021 à 23:53