John Stuart
John Stuart

Reputation: 1150

React native setInterval useState

I'm creating interval counter and below code is working fine. But I have few questions about this code which I do not understand.

import React, { useState, useEffect } from 'react';
import {View, Text} from 'react-native'

const Interval = () => {
  const [seconds, setSeconds] = useState(0);

  useEffect(() => {
    const interval = setInterval(() => {
      console.log(`seconds: ${seconds}`)
      setSeconds(seconds => seconds + 1);
    }, 1000);
    return () => clearInterval(interval);
  }, []);

  return (
      <View>
        <Text>
          {seconds} seconds have elapsed since mounting.
        </Text>
      </View>
  );
};

export default IntervalExample;
  1. Why this is not working if I put setSeconds(seconds => seconds + 1); instead setSeconds(seconds + 1); more simply ?
  2. Why console.log(`seconds: ${seconds}`) is always log as 0 ?

Upvotes: 2

Views: 1586

Answers (2)

Umut Kurt
Umut Kurt

Reputation: 106

use this ;

useEffect(() => {
    const interval = setInterval(() => {
      setSeconds(seconds + 1);
      console.log(seconds)
    }, 1000);

    return () => clearInterval(interval);
  }, [seconds]);

Upvotes: 1

Łukasz Olszewski
Łukasz Olszewski

Reputation: 915

to run useEffect You need to pass variables as the second parameter (in your case, it is seconds). When this variable has changed then useEffect will be run again.

From docs:

If you pass an empty array ([]), the props and state inside the effect will always have their initial values. While passing [] as the second argument is closer to the familiar componentDidMount and componentWillUnmount mental model, there are usually better solutions to avoid re-running effects too often. Also, don’t forget that React defers running useEffect until after the browser has painted, so doing extra work is less of a problem.

that is way, You need to pass second varable to useEfect:

useEffect(() => {...}, [seconds])

and in that case You can use setSeconds(seconds + 1); instead of passing function.

Complete code:

useEffect(() => {
 const interval = setInterval(() => {
   console.log(`seconds: ${seconds}`)
   setSeconds(seconds + 1)
  }, 1000)
 return () => clearInterval(interval)
}, [seconds])

Upvotes: 1

Related Questions