admin管理员组

文章数量:1300182

I am unable to access the state within an interval. Here I want to access counter inside interval when the counter gets equal to 10 I want to stop it.

Note: Here I don't want to put an interval inside useEffect because I need to start the interval in a specific time, by handling an event.

export default props => {

  const [counter, setCounter] = useState(0);

  const startInterval = () => {
    const timeout = setInterval(() => {
      setCounter(counter + 1);
      console.log("counter: ", counter); // alway return 0
      if(counter === 10) clearInterval(timeout);

    }, 1000);
  };

} 

I am unable to access the state within an interval. Here I want to access counter inside interval when the counter gets equal to 10 I want to stop it.

Note: Here I don't want to put an interval inside useEffect because I need to start the interval in a specific time, by handling an event.

export default props => {

  const [counter, setCounter] = useState(0);

  const startInterval = () => {
    const timeout = setInterval(() => {
      setCounter(counter + 1);
      console.log("counter: ", counter); // alway return 0
      if(counter === 10) clearInterval(timeout);

    }, 1000);
  };

} 
Share Improve this question edited Oct 23, 2019 at 6:42 Kinjal Gor 4212 gold badges5 silver badges16 bronze badges asked Oct 23, 2019 at 5:38 JaniJani 933 bronze badges 3
  • How and where are you using startInterval function – Shubham Khatri Commented Oct 23, 2019 at 5:41
  • @patrick "props is neither a hook nor a ponent" ... yes, it's the props object? – Jonas Wilms Commented Oct 23, 2019 at 5:57
  • @PatrickRoberts thank you, but the piles and execute as well, it is a function ponent with a props param exported. problem is in interval – Jani Commented Oct 23, 2019 at 6:08
Add a ment  | 

2 Answers 2

Reset to default 8

As I am seeing here even your setCounter(counter+1) wont update, because of lexical scope. So you have to change it like this:

setCounter(counter => counter + 1);

Also because of lexical scope you wont access counter to check condition, so you have to make a variable and update that inside functional ponent by asigning counter to it, then check it with if condition.

Complete Code code:

let myCounter = 0;
let timeout = null;
export default CounterApp = props => {

  const [counter, setCounter] = useState(0);

  // Also don't forget this
  useEffect(()=> {
    return ()=> clearInterval(timeout);
  }, []);      

  myCounter = counter;
  const startInterval = () => {
    timeout = setInterval(() => {
      setCounter(counter => counter + 1);
      console.log("counter: ", myCounter); // counter always return 0 but myCounter the updated value
      if(myCounter === 10) clearInterval(timeout);

    }, 1000);
  };

}

I came across this exact problem not too long ago. Hooks don't work exactly as you'd expect in relation to setInterval. I found the solution on Dan Abramov's blog: You can useRef to bine multiple useEffects. Through his useInterval implementation you can also start and stop the interval by setting the timer to null

import React, { useState, useEffect, useRef } from 'react';

function Counter() {
  const [count, setCount] = useState(0);
  const [time, setTime] = useState(null); // timer doesn't run initially

  useInterval(() => {
    // Your custom logic here
    setCount(count + 1);
  }, time);

  return <>
     <h1>{count}</h1>
     <div onClick={() => setTime(1000)}>Start</div>
     <div onClick={() => setTime(null)}>Stop</div>
  </>;
}
import React, { useState, useEffect, useRef } from 'react';

function useInterval(callback, delay) {
  const savedCallback = useRef();

  // Remember the latest callback.
  useEffect(() => {
    savedCallback.current = callback;
  }, [callback]);

  // Set up the interval.
  useEffect(() => {
    function tick() {
      savedCallback.current();
    }
    if (delay !== null) {
      let id = setInterval(tick, delay);
      return () => clearInterval(id);
    }
  }, [delay]);
}

本文标签: javascriptUnable to access state inside intervalStack Overflow