簡體   English   中英

如何在反應中使用 settimeout function 內循環更新 state?

[英]How to update state using settimeout function inside loop in react?

我正在創建 React 應用程序來可視化排序算法,我在這個問題上停了下來。 我正在遍歷 bars state 中數組的所有元素,我想交換它們(出於測試目的)。 這並沒有像我想要的那樣正常工作,因為它“忽略” setTimeout function 並立即執行。 我用 setBars 嘗試了一些東西,但它也不起作用。 我怎樣才能做到這一點,以便在setTimeout function 中設置的超時后發生交換?

const [bars, setBars] = useState([23, 63, 236, 17, 2]);

const swap = (arr, i, j) => {
 let temp = arr[i];
 arr[i] = arr[j];
 arr[j] = temp;
};

for (let i = 0; i < bars.length - 1; i++) {
 setTimeout(() => {
  swap(bars, i, i + 1);
 }, 2000);
}

您希望在組件安裝時使用useEffect掛鈎啟動進程:

useEffect(() => {
    // ...code here...
}, []);

末尾的空依賴項數組表示“僅在組件首次安裝時運行它”。

在其中,您的代碼將安排計時器回調:

for (let i = 0; i < bars.length - 1; i++) {
    setTimeout(() => {
        setBars(bars => {
            // Copy the current array
            const newBars = [...bars];
            // Do the swap
            swap(newBars, i, i + 1);
            // Set the state by returning the update
            return newBars;
        });
    }, 2000 * (i + 1));
}

請注意,它使用setBars的回調形式,以便您在當時的 state 上操作(而不是bars ,它只是第一次掛載期間使用的數組,因為您的 function 僅在第一次掛載發生時被調用) .

另請注意,間隔是2000 * (i + 1)而不僅僅是2000 這樣每次回調都會在最后一次回調后 2000 毫秒發生,因為它們都是同時安排的。

上面的另一個重要方面是它在for中使用了let ,因此每個循環體都有自己的i變量。 (如果代碼使用varletfor之外,所有回調將共享同一個i變量,該變量的值為bars.length 。)


或者,我想我可能會采用這種方法:

由於您想同時更新ibars並且最好在異步更新時使用 state setter 的回調形式(與setTimeout一樣),因此我將ibars組合成一個 state 項目(而我通常會把它們分開):

const [barState, setBarState] = useState({i: 0, bars: [23, 63, 236, 17, 2]});

然后,您將使用useEffect掛鈎在組件安裝時啟動進程,然后在每次更改barState后再次執行此操作:

useEffect(() => {
    // ...code here...
}, [barState]);

末尾包含barState的 dependencies 數組表示“在組件安裝和每次barState更改時運行它”。

在其中,您的代碼將安排計時器回調:

if (barState.i < barState.bars.length - 1) {
    setTimeout(() => {
        setBarState(({i, bars}) => {
            // Copy the current array
            bars = [...bars];
            // Do the swap
            swap(bars, i, i + 1);
            // Set the state by returning the update
            ++i;
            return {i, bars};
        });
    }, 2000);
}

現場示例:

 const { useState, useEffect } = React; const swap = (arr, i, j) => { let temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; }; function Example() { const [barState, setBarState] = useState({i: 0, bars: [23, 63, 236, 17, 2]}); useEffect(() => { if (barState.i < barState.bars.length - 1) { setTimeout(() => { setBarState(({i, bars}) => { // Copy the current array bars = [...bars]; // Do the swap swap(bars, i, i + 1); // Set the state by returning the update ++i; return {i, bars}; }); }, 2000); } }, [barState]); return <div>{barState.bars.join(", ")}</div>; } ReactDOM.render(<Example />, document.getElementById("root"));
 <div id="root"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.12.0/umd/react-dom.production.min.js"></script>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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