angelaM
angelaM

Reputation: 51

Rendering React Timer/Clock Component

I'd like some help understanding why my React Component isn't working. I'm trying work on my React/Js fundamentals by making a basic timer. The component is rendering great, just nothing is happening. I'm looking at the React Profiler on Chrome and my variables seem to be updating correctly.

I know it's basic, I'd just rather start and fix my mistakes and learn on the way.

Any help whatsoever would be greatly appreciated!

import React from 'react'

var sec = 0;
var min = 0;
var hrs = 0;
var timer_id;

// Helper Functions
function tick(){
    sec++;
    if (sec >= 60){
        sec = 0; 
        min ++;
        if (min >= 60){
            min = 0;
            hrs++;
        };
    };
}

function add(){
    tick();
    timer();
}

function timer(){
    console.log("TIMER");
    timer_id = setTimeout(add, 1000);
}

// Clock Component
class Clock extends React.Component{
    render(){
        timer();
        return (
            <div className="clock-face">
                <h4> {hrs} : {min} : {sec}</h4>
                <button 
                    onClick = {() => clearTimeout(timer_id)}> Stop </button>
                    
            </div>
        );
    
    }   
}

export default Clock;

Upvotes: 0

Views: 1058

Answers (1)

AKX
AKX

Reputation: 168986

React components only get rerendered when their props or state changes (or when forced to rerender, but we don't do that). You're updating hrs/min/sec in global variables; those aren't tracked by React.

In addition, it's not a good idea to have render() execute a side effect (timer() in your case); React may elect to render your function more than once.

Here's an example of your clock as a class component that ticks along and cleans the timer up after it's unmounted.

The magic that causes the rerendering here is this.setState being called.

import React from "react";

function divmod(a, b) {
  return [Math.floor(a / b), a % b];
}

class Clock extends React.Component {
  state = { time: 0 };
  componentDidMount() {
    this.timer = setInterval(this.tick, 1000);
  }
  componentWillUnmount() {
    clearInterval(this.timer);
  }
  tick = () => {
    this.setState(({ time }) => ({ time: time + 1 }));
  };
  render() {
    const { time } = this.state;
    const [hmins, secs] = divmod(time, 60);
    const [hrs, mins] = divmod(hmins, 60);
    return (
      <div className="clock-face">
        <h4>
          {" "}
          {hrs} : {mins} : {secs}
        </h4>
      </div>
    );
  }
}

Upvotes: 1

Related Questions