以下是在 4 秒后一次增加值的代碼,盡管我希望這批更新應該在 4 秒后僅在多次單擊時增加值。
前任。- 比方說,我點擊了“異步增加”按鈕 5 次,然后在 4 秒后計數器增加到 1、2、3、4、5 但我希望在 4 秒后它應該增加,使其變為 1,然后在 4 秒后它應該將它增加到 2,然后在 4 秒后它應該增加到 3,依此類推。
讓我知道我該如何解決這個問題。
代碼 -
const UseStateCounter = () => {
const [value, setValue] = useState(0);
const reset = () => {
setValue(0);
}
const asyncIncrease = () => {
setTimeout(() => {
setValue(prevValue => prevValue 1);
}, 4000);
}
const asyncDecrease = () => {
setTimeout(() => {
setValue(prevValue => prevValue - 1);
}, 4000);
}
return <>
<section style={{margin: '4rem 0'}}>
<h3>Counter</h3>
<h2>{value}</h2>
<button className='btn' onClick={asyncDecrease}>Async Decrease</button>
<button className='btn' onClick={reset}>Reset</button>
<button className='btn' onClick={asyncIncrease}>Async Increase</button>
</section>
</>
};
export default UseStateCounter;
uj5u.com熱心網友回復:
為此,請等待上一個更改完成,然后再開始下一個更改。例如,一種方法是使用承諾鏈;看評論:
// Promise-ified version of setTimeout
const timeout = (ms) => new Promise(resolve => setTimeout(resolve, ms));
const UseStateCounter = () => {
const [value, setValue] = useState(0);
// Remember the promise in a ref we initialize
// with a fulfilled promise
const changeRef = useRef(Promise.resolve());
/* Alternatively, if there's a lot of initialization logic
or object construction, you might use `null` above
and then:
if (!changeRef.current) {
changeRef.current = Promise.resolve();
}
*/
const reset = () => {
queueValueUpdate(0, false);
};
// A function to do the queued update
const queueValueUpdate = (change, isDelta = true) => {
changeRef.current = changeRef.current
// Wait for the previous one to complete, then
.then(() => timeout(4000)) // Add a 4s delay
// Then do the update
.then(() => setValue(prevValue => isDelta ? prevValue change : change));
};
const asyncIncrease = () => {
queueValueUpdate(1);
};
const asyncDecrease = () => {
queueValueUpdate(-1);
};
// Sadly, Stack Snippets can't handle the <>...</> form
return <React.Fragment>
<section style={{ margin: '4rem 0' }}>
<h3>Counter</h3>
<h2>{value}</h2>
<button className='btn' onClick={asyncDecrease}>Async Decrease</button>
<button className='btn' onClick={reset}>Reset</button>
<button className='btn' onClick={asyncIncrease}>Async Increase</button>
</section>
</React.Fragment>;
};
export default UseStateCounter;
現場示例:
顯示代碼片段
const {useState, useRef} = React;
// Promise-ified version of setTimeout
const timeout = (ms) => new Promise(resolve => setTimeout(resolve, ms));
const UseStateCounter = () => {
const [value, setValue] = useState(0);
// Remember the promise in a ref we initialize
// with a fulfilled promise
const changeRef = useRef(Promise.resolve());
/* Alternatively, if there's a lot of initialization logic
or object construction, you might use `null` above
and then:
if (!changeRef.current) {
changeRef.current = Promise.resolve();
}
*/
const reset = () => {
queueValueUpdate(0, false);
};
// A function to do the queued update
const queueValueUpdate = (change, isDelta = true) => {
changeRef.current = changeRef.current
// Wait for the previous one to complete, then
.then(() => timeout(4000)) // Add a 4s delay
// Then do the update
.then(() => setValue(prevValue => isDelta ? prevValue change : change));
};
const asyncIncrease = () => {
queueValueUpdate(1);
};
const asyncDecrease = () => {
queueValueUpdate(-1);
};
// Sadly, Stack Snippets can't handle the <>...</> form
return <React.Fragment>
<section style={{ margin: '4rem 0' }}>
<h3>Counter</h3>
<h2>{value}</h2>
<button className='btn' onClick={asyncDecrease}>Async Decrease</button>
<button className='btn' onClick={reset}>Reset</button>
<button className='btn' onClick={asyncIncrease}>Async Increase</button>
</section>
</React.Fragment>;
};
ReactDOM.render(<UseStateCounter />, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"></script>
注意:通常我在處理 Promise 拒絕時會發出很大的聲音,但上面的 Promise 內容都不會拒絕,所以我很樂意不打擾catchin queueValueUpdate。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/409771.html
標籤:
