0

I just wanted to know why setInterval function is not decrementing the time.... isnt setInterval is suppose to run a function again and again ? I was hoping that If I put in 100 and press submit, it will go down 1 by 1.

 class Clock extends Component{
    constructor(props){
      super(props);
      this.state = {
        seconds: 60,
      }
      console.log('this.props',this.props);
      console.log('seconds',  this.state.seconds);
    }

    componentWillMount(){
      this.timer(this.props.time);
    }

    componentDidMount(){
      setInterval(()=> this.timer(this.props.time),1000);
    }

    timer(time){
        console.log('new time',time )
        this.setState({seconds:time-1});
      }

      render(){
        return (
          <div>
          <div className="Clock-seconds">{this.state.seconds} seconds</div>
          </div>
        )}}

This is the app.jsx file- user inputs the number in seconds here and it goes to clock as props. I have time in state.

import React, {Component} from 'react';
import Clock from './Clock';
import './App.css';
import {Form, FormControl, Button} from 'react-bootstrap';


class App extends Component{
  constructor(props){
    super(props);
    this.state ={
      time: '60',
      newTime: ''
    }
  }

  changeTime(){
    this.setState({time: this.state.newTime});
  }


  render(){
    return (
      <div className="App">
        <div className = "App-title">
          Countdown to {this.state.time}
        </div>

        <Clock
         time={this.state.time}
          />

        <Form inline >
          <FormControl
            className="Deadline-input"
            placeholder='new date'
            onChange={event => this.setState({newTime: event.target.value})}
            />
          <Button onClick={() => this.changeTime()}>
            Submit
          </Button>
        </Form>

      </div>
    )
  }
}

export default App;
Ash
  • 261
  • 4
  • 16

1 Answers1

1

Every time you set the state in the timer function, you're basing it off of this.props.time, which doesn't change, the state is what's actually changing. So you need to set the state based off of the previous state. Also, why are you setting the seconds state to 60 in the constructor? Don't you want to set it to this.props.time?

I believe this is what you're trying to accomplish:

class Clock extends Component{
  constructor(props){
    super(props);
    this.state = {
      seconds: this.props.time,
    }
    console.log('this.props',this.props);
    console.log('seconds',  this.state.seconds);
  }

  componentWillMount(){
    this.timer(this.props.time);
  }

  componentDidMount(){
    setInterval(()=> this.timer(),1000);
  }

  timer(){
    console.log('new time', this.state.seconds )
    this.setState(prevState => ({
      seconds: prevState.seconds - 1
    }));
  }

  render() {
    return (
      <div>
        <div className="Clock-seconds">{this.state.seconds} seconds</div>
      </div>
    );
  }
}

EDIT: Based off of your edit, here is my new solution that only has the App component and no Clock component since it seemed like you were trying to do the same thing with two different components:

class App extends Component {
  constructor(props){
    super(props);
    this.state = {
      seconds: null
    }
  }
  componentDidMount() {
    setInterval(this.timer.bind(this), 1000);
  }
  timer() {
    if (this.state.seconds) {
      this.setState(prevState => ({
        seconds: prevState.seconds - 1
      }));
    }
  }
  handleClick(event) {
    event.preventDefault();
    this.setState({seconds: this.textInput.value});
  }
  renderClock() {
    if (this.state.seconds > 0) {
      return (<div className = 'App-title'>{this.state.seconds} Seconds</div>);
    } else if (this.state.seconds === 0) {
      return (<div className = 'App-title'>Done!</div>);
    }
  }
  render() {
    return (
      <div className="App">
        {this.renderClock()}
        <form>
          <input
            className='Deadline-input'
            placeholder='new date'
            ref={input => this.textInput = input}
            type='text'>
          </input>
          <button onClick={event => this.handleClick(event)}>Submit</button>
        </form>
      </div>
    );
  }
}

This is using normal forms, you can change it to use the Bootstrap forms. I'm not sure if that will mess anything up, but this works for me when I test it.

  • thank you for response but I have app.jsx too in which user is inputing a new time. I have time in App.jsx state and I am passing it as a prop. I am using ur code but it is not updating the time. Let me add the app.jsx so that you are more clear. – Ash Sep 19 '17 at 00:55
  • Are you just doing something like ? – Andrew Harris Sep 19 '17 at 00:57
  • I have in app.jsx to display the countdown. – Ash Sep 19 '17 at 01:00
  • Well my solution works if you do What you're trying to do right now is keep and change your time state in two different components, which is what I think your problem is. I'll try to figure out a solution. – Andrew Harris Sep 19 '17 at 01:01
  • yeah but then user is no longer inputting the seconds. I want user to input the number. – Ash Sep 19 '17 at 01:03
  • Lol thank you. It works can you explain me how you did it. I really have to know or its all for nothing. Please. thank you. – Ash Sep 19 '17 at 02:59
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/154735/discussion-between-ash-and-andrew-harris). – Ash Sep 19 '17 at 03:00