Tengo problemas para revertir un estado. Lo que estoy tratando de lograr es que cuando hago clic en un botón de reproducción (PlayContainer), cambio el contenido dentro de {reproducir}. Esta función funciona, pero tengo problemas para revertir el cambio con otro clic {detener}. (Estoy usando componentes con estilo para que los elementos tengan nombres establecidos).
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> ); }Tal vez estoy haciendo esto mal, por favor avíseme si hay algún método más fácil o mejor.
Almacenar JSX en estado React es generalmente antipatrón en React. Debe almacenar datos y representar su interfaz de usuario a partir de los datos almacenados en el estado. Almacene un valor booleano en el estado para representar el estado de reproducción/detención y represente condicionalmente un elemento u otro en función del estado actual.
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> ); }Creo que es mejor usar un booleano para play en lugar de un componente. Luego puede alternar el componente según el booleano de play de esta manera:
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> ); }Hay algunos problemas en su código. En primer lugar, está almacenando elementos JSX en un estado que es una mala idea. En segundo lugar, este componente tiene 2 declaraciones de retorno (debería dar un error). Su código se puede actualizar a esto en su lugar:
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> ); }