想了想还是决定把 useEffect 走完XD
不然有讲 useState 没讲 useEffect 好像哪里怪怪的XD???
所以就拿昨天写的终极密码游戏,加上计时功能吧!
还记得之前介绍过的 useEffect 吗?
现在学过生命周期再看官方文件,
终於看得懂它在说什麽了QQ
资料 fetch、设定 subscription、或手动改变 React component 中的 DOM 都是 side effect 的范例。无论你是否习惯将这些操作称为「side effect」(或简称「effect」),你之前可能已经在 component 中执行了这些操作。
提示:
如果你熟悉 React class 的生命周期方法,你可以把 useEffect 视为 componentDidMount,componentDidUpdate 和 componentWillUnmount 的组合。
因为计时是属於 component render 後要更新的情况,
我们就可以使用 useEffect 这个 Hook。
(之前的写法我们可能会将开始计时跟停止分别写在 componentDidMount, componentWillUnmount 上)
再来我们要在游戏开始进行计时,每秒更新一次,
因此又要派出我们熟悉的 setInterval
啦!
想要让 user 按下开始游戏才正式计时,
因此在画面上要新增「开始游戏」的按钮,
而昨天游戏只分成进行中跟恭喜答对两种状态,
所以势必要新增一个状态「尚未开始」,
状态是「尚未开始」就出现「开始游戏」的按钮,
点选「开始游戏」的按钮状态就变为「进行中」,接着出现游戏画面,并开始计时,
而当然答对後就要停止计时。
{status === "尚未开始" && <button onClick={startGame}>开始游戏</button>}
{status === "进行中" ? (
<>
<hr />
<h3>
目前范围:{guessRange[0]} - {guessRange[1]}
</h3>
<h4>请输入所猜数字:{inputNum}</h4>
<input type="number" value={inputNum} onChange={handleInput} />
<button onClick={handleChange}>送出</button>
</>
): null }
{status === "恭喜答对!" && <button onClick={resetState}>重新游戏</button>}
我们当然要先新增一个状态存计时:
const [count, setCount] = useState(0);
再来就很开心用 useEffect 里面写 setInterval 开始计时啦,
计时的方式是利用 setInterval 每一秒执行一次 setCount,
每秒将 count +1
,
像这样:
useEffect(() => {
setInterval(() => setCount((c) => c + 1), 1000);
}, []);
然後也在画面上加上 {count}
来看成果吧!
等等,为什麽还没开始游戏就开始计时了?
因为用 useEffect 会在 render 後就开始执行,
这边没有设定任何条件,
当然是元件都 render 完後就开始计时,
因此这边我们要多加一个 flag start
来控制计时与否。
像这样:
... (略)
const [start, setStart] = useState(false);
... (略)
useEffect(() => {
if (start) {
setInterval(() => setCount((c) => c + 1), 1000);
}
}, [start]);
(PS. [start]
意思是当 start 有变化时才去执行这段)
然後不要忘记在开始游戏的按钮 onClick 绑定 startGame 函数,
startGame 里面要做的事就是将 start 改为 true,还有 status 改为进行中,
像这样:
const startGame = () => {
setStart(true);
setStatus("进行中");
};
好,再让我们看一次成果吧!
等等,虽然发现计时功能有 work,
但答对之後忘了停止计时,
还记得我们之前在介绍生命周期时有讲过停止计时,
因此我们要将 clearInterval 写进来,
像这样:
const id = setInterval(() => setCount((c) => c + 1), 1000);
return () => clearInterval(id);
也别忘记在答对的时候将 start
设为 false,
让它不会再走到继续计时的条件,
像这样:
if (inputNum === answer) {
setStatus("恭喜答对!");
setInputNum("");
setStart(false);
return;
}
好,再让我们看一次成果吧!
很好!这次终於对了!
可喜可贺!
也别忘记在重新游戏绑定的函数 resetState 将计数归0,以及将 start 的值设为 false,
像这样:
setStart(false);
setCount(0);
附上今日程序:Day27 - useState (Codecademy) - 终极密码 (计时版)
其实今天在写计时上面遇到没有开始计时、没有停止计时等问题,
我是看大大写的这篇才解决问题的,
这边也提供大家参考→ 「前端攻城诗」从计数器开始的React Hook 人生
感恩大大!!!
来到倒数 3 天!说好的 Next.js 该登场了吧XD
<<: [Day 24] 自定义 REST QueryDSL 实现动态查询资料库
>>: Day15:今天我们来聊一下使用Parrot Security的 Armitage来取得远端系统的存取(Gain Access)权
递回查询 Recursive Query 『递回查询』(Recursive Query)是指 当某个...
目前discord bot已经有初步的功能了 之後写的功能一定会越来越多 决定使用cog的架构来写 ...
Day 29 - 客户说:我是个人户,但是有个理念一直很想要做看看,可以帮我网站报价吗,概念是这样....
● 这篇主要是写给初出茅芦且目前还是身为投资小白的自己 在分项介绍之前,先搞懂什麽是"金融...
Background包含哪些属性? Background是缩写,包含了以下几个CSS属性 back...