亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

ReactJS useState hook 實際值在異步承諾中已過時

ReactJS useState hook 實際值在異步承諾中已過時

絕地無雙 2023-11-02 21:00:13
在我的反應函數組件中,我發送多個服務器請求并通過異步承諾更新狀態掛鉤值,方法是將服務器結果附加到狀態最新值,但是一旦創建承諾,狀態掛鉤的值不會在運行的承諾內更新,因此如果另一個Promise 更新狀態值,其他正在運行的 Promise 不會收到通知,因此它們使用舊版本的狀態來進行進一步的狀態更新。下面的代碼是我的組件的簡化版本,我希望在多個 Promise 運行且狀態更新時,從每個 Promise 的第 19 行控制臺日志中看到相同(且最新)的值。function App() {  const [myArray, setMyArray] = useState([0,1,2])  const sleep = (ms:number) => {    return new Promise(resolve => setTimeout(resolve, ms));  }  const updateArray = () => {    setMyArray([...myArray, myArray.length])  }  const firePromise = () => {    new Promise(async (resolve) => {      const timeStamp = new Date().getTime()      let repeatTime = 0      while(repeatTime < 12){        console.log("array: ", myArray, "promiseIdenifier: ", timeStamp);        repeatTime += 1        await sleep(1000)      }      resolve({timeStamp, myArray})    }).then(val => {      console.log("resolved: ", val);          }).catch(err => {      console.log("rejected: ", err);          })  }  return (    <div className="App">      <button onClick={firePromise}>new promise</button>      <button onClick={updateArray}>updateArray</button>    </div>  );}export default App;  
查看完整描述

1 回答

?
桃花長相依

TA貢獻1860條經驗 獲得超8個贊

一旦 React 組件被渲染,就可以假設組件的當前“狀態”像快照一樣存在。


console.log 中的“myArray”是創建 firePromise 時的“myArray”。所以保留第一個值是正確的。(每次渲染組件時,都會創建一個新的 firePromise。)


有一種方法。第一個是使用 ref,第二個是使用 setState。


第一的


function App() {

? const myArray = useRef<Array<number>>([0, 1, 2]);

? const sleep = (ms: number) => {

? ? return new Promise((resolve) => setTimeout(resolve, ms));

? };

? const updateArray = () => {

? ? myArray.current.push(myArray.current.length);

? };

? const firePromise = () => {

? ? new Promise(async (resolve) => {

? ? ? const timeStamp = new Date().getTime();

? ? ? let repeatTime = 0;

? ? ? while (repeatTime < 12) {

? ? ? ? console.log(

? ? ? ? ? "array: ",

? ? ? ? ? myArray.current,

? ? ? ? ? "promiseIdenifier: ",

? ? ? ? ? timeStamp

? ? ? ? );

? ? ? ? repeatTime += 1;

? ? ? ? await sleep(1000);

? ? ? }

? ? ? resolve({ timeStamp, myArray: myArray.current });

? ? })

? ? ? .then((val) => {

? ? ? ? console.log("resolved: ", val);

? ? ? })

? ? ? .catch((err) => {

? ? ? ? console.log("rejected: ", err);

? ? ? });

? };

? return (

? ? <div className="App">

? ? ? <button onClick={firePromise}>new promise</button>

? ? ? <button onClick={updateArray}>updateArray</button>

? ? </div>

? );

}


export default App;

第二


function App() {

? const [myArray, setMyArray] = useState([0, 1, 2]);

? const sleep = (ms: number) => {

? ? return new Promise((resolve) => setTimeout(resolve, ms));

? };

? const updateArray = () => {

? ? setMyArray([...myArray, myArray.length]);

? };

? const firePromise = () => {

? ? new Promise(async (resolve) => {

? ? ? const timeStamp = new Date().getTime();

? ? ? let repeatTime = 0;

? ? ? while (repeatTime < 12) {

? ? ? ? setMyArray((prevMyArray) => {

? ? ? ? ? console.log("array: ", prevMyArray, "promiseIdenifier: ", timeStamp);

? ? ? ? ? return prevMyArray;

? ? ? ? });

? ? ? ? repeatTime += 1;

? ? ? ? await sleep(1000);

? ? ? }

? ? ? setMyArray((prevMyArray) => {

? ? ? ? resolve({ timeStamp, prevMyArray });

? ? ? ? return prevMyArray;

? ? ? });

? ? })

? ? ? .then((val) => {

? ? ? ? console.log("resolved: ", val);

? ? ? })

? ? ? .catch((err) => {

? ? ? ? console.log("rejected: ", err);

? ? ? });

? };

? return (

? ? <div className="App">

? ? ? <button onClick={firePromise}>new promise</button>

? ? ? <button onClick={updateArray}>updateArray</button>

? ? </div>

? );

}


export default App;

將回調傳遞給 setState 函數時,當前狀態將作為第一個參數傳遞。這是使用這個的快捷方式。


建議使用當值改變時視圖應該改變的值作為狀態。更改“myArray”不會影響視圖,因此使用 ref 是正確的方法。


查看完整回答
反對 回復 2023-11-02
  • 1 回答
  • 0 關注
  • 164 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號