En el proceso de aprendizaje, reacciona y solo crea un juego simple de adivinanzas con fines prácticos.
En mi código, tengo un componente llamado 'Juego' con 'const roll = Math.floor(Math.random() * 10 + 1)' para obtener un número aleatorio entre 1 y 10 y verificar el resultado mediante console.log. Puedo ver el número que aparece en la consola.
Luego uso {roll} en mi declaración de devolución que luego se instancia en mi archivo App.js (App.js no se muestra a continuación)
Lo único es que el número aleatorio obtenido cuando se usa console.log(roll) es diferente al número que aparece en la pantalla en mi declaración de devolución 'El número obtenido es {roll}'
¿Por qué es esto? Nunca tuve este problema en JavaScript estándar, pero parece que el rollo ocurre dos veces en lugar de tomar el valor inicial en 'const roll'
¿Alguien puede explicar por qué este es el caso y cómo solucionar este problema? Gracias por cualquier ayuda que pueda obtener
import React, {useState} from "react"; const Game = () => { const roll = Math.floor(Math.random() * 10 + 1); console.log(roll); const guess = () => { let inputGuess = document.querySelector('.input'); console.log(inputGuess.value); } const [lives, setLives] = useState(5); return ( <React.Fragment> <h1 className='header'>Guess the number!</h1> <p className='roll'>The number rolled is <strong>{roll}</strong></p> <p className='lives'><strong>{lives}</strong> lives remaining</p> <p className='message'>Enter a number between 1-10</p> <input type='text' className='input'></input> <button className='guess' onClick={guess}>Guess</button> </React.Fragment> ) } export default Game;En el modo de desarrollo, React invoca intencionalmente los cuerpos de los componentes de funciones (y otros métodos del ciclo de vida) dos veces para ayudar a identificar los efectos secundarios:
El modo estricto no puede detectar automáticamente los efectos secundarios, pero puede ayudarlo a detectarlos haciéndolos un poco más deterministas. Esto se hace mediante una doble invocación intencional de las siguientes funciones:
para agregar a la respuesta por ray hatfield
Debe considerar que su variable de roll se volverá a declarar (y, por lo tanto, será un nuevo número aleatorio) en cada renderizado. El componente se volverá a renderizar cada vez que se actualice el estado de lives y cada vez que se vuelva a renderizar el componente principal.
Para evitar la reasignación de la variable roll, debe colocarla en su propio useState .
Probar:
const Game = () => { const roll = Math.floor(Math.random() * 10 + 1); const [roll2, setRoll] = React.useState(Math.floor(Math.random() * 10 + 1)); console.log('Without useState: ', roll); console.log('With useState: ', roll2); const guess = () => { let inputGuess = document.querySelector('.input'); console.log(inputGuess.value); } const [lives, setLives] = React.useState(5); return ( <React.Fragment> <h1 className='header'>Guess the number!</h1> <p className='roll'>The number rolled is <strong>{roll}</strong></p> <p className='lives'><strong>{lives}</strong> lives remaining</p> <p className='message'>Enter a number between 1-10</p> <input type='text' className='input'></input> <button className='guess' onClick={guess}>Guess</button> </React.Fragment> ) }; const App = () => { console.log('re-rendering App'); const [state, setState] = React.useState(0); // we are faking an update to the parent component React.useEffect(() => { setInterval(() => setState((prev) => ++prev), [2000]); }, []); return <div><Game /></div>; } ReactDOM.render(<App />, document.getElementById('app')); <script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin ></script> <script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin ></script> <div id="app"></div>