簡體   English   中英

為什么不在功能組件中狀態更新

[英]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捕獲了從第一次渲染傳遞給 CountDown initValue的初始值。 我們從不重新應用效果,因此 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM