我想在用户单击按钮时执行setInterval
,除了调用clearInterval
之外,所有逻辑对我而言都是可以的。
在props.time === 0
时,我要执行clearInterval
。但是,我发现无法更新props.time
。它始终等于setInterval
回调中的初始值。
我是反应和反应挂钩的新手。我发现诸如useEffect
,useRef
之类的钩子可以帮助我解决问题。但是,我不明白如何使用它。我希望有人能给我一些提示。
谢谢
const [timer, setTimer] = useState(undefined)
const countDown = () => {
const timerInterval = setInterval(() => {
if (props.time === 0) clearInterval(timer)
// execute the logic of "props.time = props.time - 1"
}, 1000)
setTimer(timerInterval)
}
return (
<button onClick={countDown} />
)
答案 0 :(得分:1)
看看这就是您要寻找的东西。
useRef
是保留setInterval
引用的正确位置。每个渲染上都会有相同的参考。它不会改变。
从React DOCS:
https://reactjs.org/docs/hooks-reference.html#useref
useRef
但是,useRef()不仅对ref属性有用。与在类中使用实例字段的方式类似,保留任何可变值都很方便。
之所以有效,是因为useRef()创建了一个纯JavaScript对象。 useRef()和自己创建{current:...}对象之间的唯一区别是useRef将在每个渲染器上为您提供相同的ref对象。
请记住,当useRef的内容更改时,它不会通知您。更改.current属性不会导致重新渲染。如果您想在React将ref附加或分离到DOM节点时运行一些代码,则可能要改用回调ref。
function App() {
const [time, setTime] = React.useState(0);
const timerRef = React.useRef(null);
if (time === 0) {
clearInterval(timerRef.current);
}
function countDown(startFrom) {
setTime(startFrom);
timerRef.current = setInterval(() => {
setTime((prevState) => prevState -1);
}, 1000);
}
return (
<React.Fragment>
<div>Time: {time}</div>
<button onClick={()=>countDown(3)}>Countdown from 3</button>
<button onClick={()=>countDown(5)}>Countdown from 5</button>
</React.Fragment>
);
}
ReactDOM.render(<App/>, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"/>