REACT,有一个滚动num 1-10的变量,并在JSX的return语句中连接该变量.数字在屏幕上渲染之前滚动2倍



在学习的过程中做出反应,并为练习目的构建一个简单的数字猜测游戏

在我的代码中,我有一个名为"Game"的组件,带有"const roll=Math.floor(Math.random((*10+1(",可以滚动1-10之间的随机数,并通过console.log验证滚动,这样我就可以看到控制台上显示的数字。

然后,我在返回语句中使用{roll},该语句稍后在我的App.js文件中实例化(下面没有显示App.js(

唯一的问题是,使用console.log(roll(时滚动的随机数与我的返回语句"滚动的数字是{roll}"中屏幕上呈现的数字不同

为什么会这样?我在vanilla JavaScript中从未遇到过这个问题,但滚动似乎发生了两次,而不是在"const roll"中取初始值

有人能解释为什么会出现这种情况以及如何解决这个问题吗?谢谢你的帮助,我可以得到

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;

在开发模式中,React有意调用功能组件体(和其他生命周期方法(两次,以帮助识别副作用:

严格模式不能自动为您检测副作用,但它可以通过使它们更具确定性来帮助您发现它们。这是通过有意地双重调用以下函数来实现的:

  • 类组件构造函数、render和shouldComponentUpdate方法
  • 类组件静态getDerivedStateFromProps方法
  • 功能组件主体
  • 状态更新器函数(setState的第一个参数(
  • 传递给useState、useMemo或useReducer的函数

通过ray hatfield添加到答案

您应该考虑,roll变量将在每次渲染时重新声明(因此是一个新的随机数(。每当lives状态更新时,以及每当父组件重新渲染时,该组件都将重新渲染。

为了防止roll变量的重新分配,您应该将其放置在自己的useState挂钩中。

尝试:

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>

最新更新