import {useEffect,useState} from 'react';
export default function App() {
const [count,setCount]=useState(0);
const [flag,setFlag]=useState(false);
function increment(){
setCount(prevState=>{
if(flag)
return prevState
return prevState 1;
});
}
useEffect(function(){
increment();
setFlag(true);
increment();
},[]);
return (
<div className="App">
{count}
</div>
);
}
在 reatct 功能組件中玩弄效果和狀態,我希望代碼輸出“1”,但它給出的輸出為“2”,為什么會發生,我怎樣才能讓它列印 1?
uj5u.com熱心網友回復:
一旦你呼叫,React 將在下一次渲染時更新你呼叫 的setFlag回傳值。useState[flag,_] = useState()
您的setFlag(true)呼叫安排了重新渲染,它不會立即更新函式中的值。
你畢竟flag是一個布林值const——它不能是任何值,只能是該函式呼叫中的一個值。
如何解決它變得有趣;你可以把flag單個狀態物件的內部,即useState({count: 0, flag: false})
但更有可能的是,這是一個學術問題。計數增量聽起來像是在用戶互動(如 a)時觸發的東西,click只要一個函式不多次呼叫 increment()(這聽起來很不尋常),重新渲染就會及時發生以更新您的flag狀態。
uj5u.com熱心網友回復:
出于性能原因,React 將useState鉤子更新延遲到函式完成執行,即運行函式體中的所有陳述句然后更新組件狀態,因此 React 將更新程序延遲到稍后的時間。
因此,當increment函式執行完成時,React 會更新count. 但是對于setFlagmethod來說,執行環境是useEffecthook回呼的背景關系,所以這里React還在等待useEffect的回呼函式完成。因此,在回呼里面的useEffect值flag仍然是false.
然后你再次呼叫你的increment函式,當這個函式完成執行時,你的count又增加了1.
因此,在您的情況下,關鍵因素是將狀態更新推遲到 React 函式執行的方式。
將 setState() 視為更新組件的請求而不是立即命令。為了更好地感知性能,React 可能會延遲它,然后一次更新多個組件。React 不保證立即應用狀態更改。
setState() 并不總是立即更新組件。它可能會批量更新或將更新推遲到以后。這使得在呼叫 setState() 之后立即讀取 this.state 是一個潛在的陷阱。相反,使用 componentDidUpdate 或 setState 回呼 (setState(updater, callback)),它們都保證在應用更新后觸發。如果您需要根據之前的狀態設定狀態,請閱讀下面的 updater 引數。
反應組件:setState()
有關更多資訊,您還可以閱讀Batch updatesReact(尤其是 React 18)或Reactive programming(這不是 React),其中主要思想是實時或及時更新。
uj5u.com熱心網友回復:
為了更好地理解,我認為它直接用 setter 替換呼叫,我們知道狀態批處理是如何作業的,所以......
import { useEffect, useState } from "react";
export default function App() {
const [count, setCount] = useState(0);
const [flag, setFlag] = useState(false);
useEffect(function () {
// increment(); becomes below
setCount((prevState) => {
if (flag) return prevState;
return prevState 1;
});
// queued update count returns
// count => count 1 0 0 1 = 1
setFlag(true);
//set flag=true in next render
// increment(); becomes below
setCount((prevState) => {
if (flag) return prevState;
return prevState 1;
});
// so flag is still false here and count is 1
// queued update count returns
// count => count 1 1 1 1 = 2
// done and count for next render is 2 and flag will be false
}, []);
return <div className="App">{count}</div>;
Docs 中更好的解釋 -排隊狀態更新和狀態為快照
uj5u.com熱心網友回復:
狀態更新是“批量”的。請參閱其他答案以獲取解釋。這是一種解決方法useRef- 由于可以在此渲染期間更新 ref,因此您可以像“正常”變數一樣使用它。
const { useState, useRef, useEffect } = React;
function App() {
const [count, setCount] = useState(0);
const flag = useRef(false);
function increment() {
setCount(prevState => {
if (flag.current)
return prevState;
return prevState 1;
});
}
useEffect(function() {
increment();
flag.current = true;
increment();
}, []);
return <div className="App">{count}</div>;
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/522648.html
上一篇:反應樣式的條件類名稱設定
