如何通过使用React钩子在setInterval中获取更新的道具?

时间:2019-07-15 08:50:33

标签: reactjs setinterval react-hooks

我想在用户单击按钮时执行setInterval,除了调用clearInterval之外,所有逻辑对我而言都是可以的。

props.time === 0时,我要执行clearInterval。但是,我发现无法更新props.time。它始终等于setInterval回调中的初始值。

我是反应和反应挂钩的新手。我发现诸如useEffectuseRef之类的钩子可以帮助我解决问题。但是,我不明白如何使用它。我希望有人能给我一些提示。

谢谢

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} />
)

1 个答案:

答案 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"/>