我想從函式中減去“百分比”的值 0.25。
但是,減法不起作用。
我使用了setState,但我不知道為什么它不起作用。
import React, {useState, useRef, useCallback} from 'react';
const Ques = () => {
const [percent,setPercent] = useState(1);
const intervalRef = useRef(null);
const start = useCallback(() =>{
if (intervalRef.current !== null){
return;
}
intervalRef.current = setInterval(()=>{
if (percent > 0){
setPercent(c => c - 0.25);
console.log("percent = ", percent);
}
else {
setPercent(c => 1);
}
}, 1000);
}, []);
return (
<div>
<button onClick={()=>{start()}}>{"Start"}</button>
</div>
);
}
export default Ques;
uj5u.com熱心網友回復:
問題
排隊狀態更新作業正常,但您在記錄的間隔回呼中對狀態有一個陳舊的外殼percent,它永遠不會更新。
解決方案
如果要記錄percent狀態,請使用useEffect掛鉤記錄更改。
const Ques = () => {
const [percent, setPercent] = useState(1);
const intervalRef = useRef(null);
useEffect(() => {
console.log("percent = ", percent); // <-- log state changes here
}, [percent]);
const start = useCallback(() => {
if (intervalRef.current !== null) {
return;
}
intervalRef.current = setInterval(() => {
setPercent((c) => Math.max(0, c - 0.25)); // <-- simpler updater function
}, 1000);
}, []);
return (
<div>
Percent: {percent * 100}
<button onClick={start}>Start</button>
</div>
);
};
uj5u.com熱心網友回復:
我認為useCallback并useRef不太合適。下面是一個使用useStateand的最小可驗證示例useEffect。請注意,當組件卸載時,此函式會適當地對計時器執行清理。點擊Run運行代碼片段,點擊start開始運行效果。
function App() {
const [percent, setPercent] = React.useState(1)
const [running, setRunning] = React.useState(false)
React.useEffect(() => {
if (!running) return
const t = window.setTimeout(() => {
setPercent(c => c > 0 ? c - 0.25 : 1)
}, 1000)
return () => window.clearTimeout(t)
}, [running, percent])
return <div>
<button onClick={() => setRunning(true)} children="start" />
<pre>percent: {percent}</pre>
</div>
}
ReactDOM.render(<App/>, document.querySelector("#app"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.14.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.14.0/umd/react-dom.production.min.js"></script>
<div id="app"></div>
uj5u.com熱心網友回復:
您也可以創建一個reffor percent 并將其current值更改為:
codesandbox link
import React, { useRef, useCallback } from "react";
const Ques = () => {
const percentRef = useRef(1);
const intervalRef = useRef(null);
const start = useCallback(() => {
if (intervalRef.current !== null) {
return;
}
intervalRef.current = setInterval(() => {
console.log("percent = ", percentRef.current);
percentRef.current > 0
? (percentRef.current -= 0.25)
: (percentRef.current = 1);
}, 1000);
}, []);
return (
<div>
<button onClick={start}>Start</button>
</div>
);
};
export default Ques;
uj5u.com熱心網友回復:
這可能是實作預期目標的一種可能解決方案:
代碼片段
const {useState, useRef, useCallback} = React;
const Ques = () => {
const [percent,setPercent] = useState(1);
const intervalRef = useRef(null);
const start = useCallback((flag) => {
if (intervalRef.current !== null){
if (flag && flag === 'end') clearInterval(intervalRef.current);
return;
}
intervalRef.current = setInterval(() => {
setPercent(
prev => (prev > 0 ? prev - 0.25 : 1),
console.log('percent: ', percent)
);
/*if (percent > 0){
setPercent(c => c - 0.25);
console.log("percent = ", percent);
}
else {
setPercent(1);
}*/
}, 1000);
}, []);
return (
<div>
percent: {percent} <br/> <br/>
<button onClick={() => start('bgn')}>Start</button>  
<button onClick={() => start('end')}>Stop</button>
</div>
);
}
ReactDOM.render(
<div>
<h3>DEMO</h3>
<Ques />
</div>,
document.getElementById('rd')
);
<div id='rd' />
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>
解釋
- 有兩個按鈕
Start和Stop - 兩者都呼叫相同的
start方法,但使用不同的引數 (flag) - 如果
intervalRef已經設定(即不為空)并且flag是end,則清除間隔 - 被
percent添加到 UI 以查看其值的實時變化 setPercent修改為使用prev(保持正確的狀態)
uj5u.com熱心網友回復:
<button onClick={()=>{start()}}>{"Start"}</button>
應該
<button onClick={()=>{start();}}>{"Start"}</button>
也嘗試添加setPercent到depuseCallback
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/444594.html
上一篇:ifelse回圈的問題
