Home  >  Q&A  >  body text

useState not updated

Can you tell me why my useState is still empty? It doesn't want to update it. I'm using setInteraval and a function to update data and want to set useState at the current time, but useState ignores formatTime in setTimeOut(res) . Can you tell me how to fix it?

EDIT: If I put the number into useState

const [timeOut, setTimeOut] = useState(30)

It appears for a second and then disappears and I have empty fields. It seems like setInterval deletes everything inside, so how to fix it?

const Timer = ({item}) => {

  const [timeOut, setTimeOut] = useState('')  // << doent want to update it from 
                                              //         formatTime function
  console.log(timeOut) // still empty


useEffect(() => {
    if (status !== 'unPaid') return;

    const timer = window.setInterval(() => {
        setTimeOut(formatTime(createdAt));
    }, 1000);

    return () => window.clearInterval(timer);
}, [createdAt, status]);



const formatTime = (time) => {
         console.log(time) //  2023-07-25T23:39:39.253Z

         // const timer = new Date(time).getTime() + 1800000
          const timer = new Date(time).getTime() + 250000
          let countDown = new Date().getTime()
          let distance = timer - countDown

          let min = Math.floor((distance % (1000*60*60) / (1000*60)))
          let sec = Math.floor((distance % (1000*60) / (1000)))
          let res = Math.abs(min) + ':' + Math.abs(sec)
          console.log(res)   //  4:50
          setTimeOut(res)   // <<<<<   it doesnt want to apdate my useState
           
 }

P粉245003607P粉245003607373 days ago491

reply all(2)I'll reply

  • P粉103739566

    P粉1037395662023-09-15 17:42:24

    This is most likely because you are setting the state within a timeout.

    Another problem is that you are calling setTimeout inside it.

    Instead, use a function that returns a new value based on the previous state.

    useState Accepts a function that receives previousState as a parameter

    const [count, setCount] = useState(0);
    
    useEffect(() => {
      window.setTimeout(() => {
        setCount((prevValue) => {
          return prevValue + 1; // what you return here, will be the new state.
        })
      }, 1000)
    }, []);

    reply
    0
  • P粉990008428

    P粉9900084282023-09-15 09:23:00

    Looks like the problem is that setInterval runs every second and updates the status (timeOut) every second.

    Also, in the formatTime function, you are using the current time (new Date().getTime()) instead of the createdAt time. Therefore, the status is constantly updated with new values ​​every second.

    This is the updated code.

    const Timer = ({ item }) => {
      const [timeOut, setTimeOut] = useState('');
    
      useEffect(() => {
        if (status !== 'unPaid') return;
    
        const timer = window.setInterval(() => {
          setTimeOut(formatTime(createdAt));
        }, 1000);
    
        return () => window.clearInterval(timer);
      }, [createdAt, status]);
    
      const formatTime = (time) => {
        const timer = new Date(time).getTime() + 250000;
        const currentTime = new Date().getTime();
        const distance = timer - currentTime;
    
        let min = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
        let sec = Math.floor((distance % (1000 * 60)) / 1000);
        let res = Math.abs(min) + ':' + Math.abs(sec).toString().padStart(2, '0');
        return res;
      };
    
      return <div>{timeOut}</div>;
    };

    reply
    0
  • Cancelreply