31

I want to show the current time(MM/DD/YY hh:mm:ss) in react native app like a clock, and get update every seconds, I tried using new Date() and set it in state, but the time don't update unless I refresh the page. I also tried using setInterval function in render(), it do got update but it's expensive for CPU. is there a good method to realise the function?

state = {
    curTime: null,
}
render(){
    setInterval(function(){this.setState({curTime: new  Date().toLocaleString()});}.bind(this), 1000);
    return (
        <View>
            <Text style={headerStyle.marginBottom15}>Date: {this.state.curTime}</Text>
        </View>
    );
}
inoutwhy
  • 624
  • 1
  • 6
  • 12

8 Answers8

55

Just move setInterval into componentDidMount function.

Like this :

  componentDidMount() {
    setInterval(() => {
      this.setState({
        curTime : new Date().toLocaleString()
      })
    }, 1000)
  }

This will change state and update every 1s.

Nguyên Hoàng
  • 1,043
  • 9
  • 11
21

in react hooks, it can be done like this:

import React, { useState, useEffect } from "react";

const [dt, setDt] = useState(new Date().toLocaleString());

useEffect(() => {
    let secTimer = setInterval( () => {
      setDt(new Date().toLocaleString())
    },1000)

    return () => clearInterval(secTimer);
}, []);
Ilana Hakim
  • 762
  • 6
  • 10
15

This method works fine and displays MM/DD/YY hh:mm:ss format

class Clock extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          time: new Date().toLocaleString()
        };
      }
      componentDidMount() {
        this.intervalID = setInterval(
          () => this.tick(),
          1000
        );
      }
      componentWillUnmount() {
        clearInterval(this.intervalID);
      }
      tick() {
        this.setState({
          time: new Date().toLocaleString()
        });
      }
      render() {
        return (
          <p className="App-clock">
            The time is {this.state.time}.
          </p>
        );
      }
    }

original link : https://openclassrooms.com/courses/build-web-apps-with-reactjs/build-a-ticking-clock-component

Kuhan
  • 495
  • 7
  • 17
3

I got the answer. The code below also works.

componentWillMount(){
    setInterval(function(){
        this.setState({
            curTime: new Date().toLocaleString()
        })
    }.bind(this), 1000);
}
Pang
  • 9,564
  • 146
  • 81
  • 122
inoutwhy
  • 624
  • 1
  • 6
  • 12
  • But if I don't .bind(this), I got this error: this.setState is not a function. – inoutwhy Dec 23 '16 at 07:26
  • Yes, I have saw your example, it's a little different from mine, you pass a es6 arrow function as first param in setInterval. here is my full code: – inoutwhy Dec 23 '16 at 09:57
  • Sorry, not able to past my full code here for characters length limit here. – inoutwhy Dec 23 '16 at 10:00
3

I would recommend to prefer using setTimeout instead of setInterval, indeed, the browser may be overhelmed by heavy processing and in that case you would probably prefer updating the clock less often instead of queuing several updates of the state.

With setTimeout it is also a bit easier to leverage the Page Visibility API to completely stop the clock when the page is hidden (see https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API).

export default class MyClock {
  constructor(props) {
    super(props);

    this.state = {
      currentTime: Date.now(),
    }; 
  }

  updateCurrentTime() {
    this.setState(state => ({
      ...state,
      currentTime: Date.now(),
    }));
    this.timeoutId = setTimeout(this.updateCurrentTime.bind(this), 1000);
  }

  componentWillMount() {
    this.updateCurrentTime();
    document.addEventListener('visibilitychange', () => {
      if(document.hidden) {
        clearTimeout(this.timeoutId);
      } else {
        this.updateCurrentTime();
      }
    }, false);
  }

  componentWillUnmount() {
    clearTimeout(this.timeoutId);
  }
} 
nfroidure
  • 1,531
  • 12
  • 20
0

Full Code here:

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


export default class KenTest extends Component {

  componentDidMount(){ 

    setInterval(() => (

      this.setState(
        { curTime : new Date().toLocaleString()}

      )
    ), 1000);
  }


state = {curTime:new Date().toLocaleString()};


  render() {
    return (
      <View>
  <Text>{'\n'}{'\n'}{'\n'}The time is: {this.state.curTime}</Text>

      </View>
    );
  }
}
Ken Lee
  • 6,985
  • 3
  • 10
  • 29
0

Using hooks and moment-js:

setInterval(() => {
  var date = moment().utcOffset("-03:00").format(" hh:mm:ss a");
  setCurrentDate(date);
}, 1000);
  • Please add further details to expand on your answer, such as working code or documentation citations. – Community Sep 05 '21 at 16:43
  • This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). – Martin Sep 06 '21 at 11:59
  • This should only be a comment to Ilana Hakim's [answer](https://stackoverflow.com/a/60998067/1280867). It adds nothing new with regard to how the original question can be solved via hooks. – Martin Sep 06 '21 at 12:01
0

Try this,

import * as React from 'react';
import { Text, View } from 'react-native';


export default function App() {
  const [time, setTime] = React.useState();

  React.useEffect(() => {
    const timer = setInterval(() => {
      setTime(new Date().toLocaleString());
    }, 1000);

    return () => {
      clearInterval(timer);
    };
  }, []);

  return (
    <View>
      <Text>{time}</Text>
    </View>
  );
}
Codemaker2015
  • 12,190
  • 6
  • 97
  • 81