![](/img/trans.png)
[英]Change to React State doesn't update display in functional component
[英]Why doesn't state update in functional component
我創建了一個簡單的組件,但狀態更新有問題。 我知道正確的解決方案,但我的問題是:為什么這段代碼不起作用?
import * as React from "react"; import {useEffect, useState} from "react"; type CountdownProps = { start: number; } export const Countdown: React.FunctionComponent<CountdownProps> = ({start}: CountdownProps) => { const [seconds, setSeconds] = useState<number>(start); useEffect(() => { setInterval(() => setSeconds(seconds - 1), 1000); }, []); return (<>{seconds}</>); };
這是一個已知的問題作出反應掛鈎,當談到useInterval丹在他的博客帖子的人談論反應過度
問題是
useEffect
捕獲了從第一次渲染傳遞給 CountDowninitValue
的初始值。 我們從不重新應用效果,因此 setInterval 中的閉包始終引用第一次渲染中的initValue
,並且initValue - 1
始終為initValue
。
有趣的事實
您實際上可以通過在語句中添加一個
console.log
來檢查間隔實際上是否每秒更新一次,但它總是得到initValue
。 在這里嘗試一下https://repl.it/repls/MedicalMealyPentagon
有關解決方案,請閱讀上面的文章。
進入 setTimeout 或 setInterval,您還沒有訪問全局上下文,您必須調用秒回調函數,該函數將為您提供最新值,您需要返回新的秒值,如下所示:
import * as React from "react"; import {useEffect, useState} from "react"; type CountdownProps = { start: number; } export const Countdown: React.FunctionComponent<CountdownProps> = ({start}) => { const [seconds, setSeconds] = useState<number>(start); useEffect(() => { setInterval(() => setSeconds(preSeconds => preSeconds - 1), 1000); }, []); return (<>{seconds}</>); };
問題是在您提供給 setInterval 的函數中, seconds
的值永遠不會更新。 您的函數每 1000 毫秒運行一次,但該值不會更改,因為所提供函數中的seconds
永遠不會更新。
您可以使用 setTimeout 代替 setInterval 並使 useEffect 依賴於這樣的seconds
:
import React, { useEffect, useState } from "react";
export default function App() {
const [seconds, setSeconds] = useState(100);
useEffect(() => {
setTimeout(() => setSeconds(seconds - 1), 1000);
}, [seconds]);
return <>{seconds}</>;
}
您需要將構造函數值添加到 usestate(I added 0) 另外useEffect的第二個參數應該是seconds
我也將React.FunctionComponent更改為React.FC
關於第二個參數的更多信息:
React 的 useEffect 鈎子的第二個參數是 useEffect 回調的依賴項數組。 當該數組中的任何值發生更改時,將重新運行效果回調。
import * as React from "react";
import {useEffect, useState} from "react";
type CountdownProps = {
start: number;
}
const Countdown: React.FC<CountdownProps> = ({start}: CountdownProps) => {
start = 0;
const [seconds, setSeconds] = useState<number>(start);
useEffect(() => { const id = setInterval(() => { setSeconds(seconds - 1) }, 1000); return () => clearInterval(id); }, [seconds])
return (<>{seconds}</>);
};
export default Countdown;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.