3

I have made 2 buttons and one input field. Buttons (+/-) are to increment and decrement the counter. Initially the input field contents the date i.e data.available_slots[0].date

When I increment by clicking on + button the date changes dynamically from Wed, Dec 06 to Thur, Dec07 to Fri, Dec08 and so on to last date i.e Wed, Dec13.

The length of JSONdata is 7 i.e data.available_slots[0].date to data.available_slots[6].date so when the counter reaches 6 it should not increment further and if counter gets decremented then it should not go below 0.

But now when the counter(index) gets out of the bound it displays error (see screenshot)

See various screenshots which on click buttons display various dates in input field https://i.sstatic.net/xOvWO.jpg

datepicker.js:

import React, { Component } from 'react';
import data from './data';
import './datepicker.css';

class DatePicker extends Component {

  constructor(props){
    super(props);
     this.state = {
        counter:0
     };
   }

  increment(){
    this.setState({
      counter: this.state.counter + 1
    });
  }

  decrement(){
    if(this.state.counter > 0){
      this.setState(prevState => ({counter: prevState.counter-1}))
   }
  }


  render() {
    return (
      <div>
        <div id="center">
            <label for="name">Pick a Date </label>
            <p></p>
            <button type="button" className="btn btn-success" id="plus" onClick={this.increment.bind(this)}>+</button>
            <input type="text" id="date" value={data.available_slots[this.state.counter].date}/>
            <button type="button" className="btn btn-danger" id="minus" onClick={this.decrement.bind(this)}>-</button> 
        </div>
      </div>
    );
  }
}

export default DatePicker;

data.js:

const data = {
        "template_type": "slot_picker",
        "selection_color": "#000000",
        "secondary_color": "#808080",
        "title": "Available Slots for Dr. Sumit",
        "available_slots": [
          {
            "date": "Wed, Dec 06",
            "date_slots": [

            ]
          },
          {
            "date": "Thu, Dec 07",
            "date_slots": [

            ]
          },
          {
            "date": "Fri, Dec 08",
            "date_slots": [

            ]
          },
          {
            "date": "Sat, Dec 09",
            "date_slots": [

            ]
          },
          {
            "date": "Today",
            "date_slots": [
              {
                "hour": "8",
                "hour_slots": [
                  {
                    "08:10 AM": "slotId001"
                  },
                  {
                    "08:50 AM": "slotId005"
                  }
                ]
              },
              {
                "hour": "3",
                "hour_slots": [
                  {
                    "03:00 PM": "slotId005"
                  },
                  {
                    "03:30 PM": "slotId007"
                  }
                ]
              }
            ]
          },
          {
            "date": "Tomorrow",
            "date_slots": [

            ]
          },
          {
            "date": "Wed, Dec 13",
            "date_slots": [
              {
                "hour": "4",
                "hour_slots": [
                  {
                    "04:30 PM": "slotId105"
                  },
                  {
                    "04:50 PM": "slotId106"
                  }
                ]
              },
              {
                "hour": "5",
                "hour_slots": [
                  {
                    "05:30 PM": "slotId202"
                  },
                  {
                    "05:45 PM": "slotId208"
                  }
                ]
              }
            ]
          }
        ]
      };

 export default data;

enter image description here

5
  • You can test the input value to depress the out-of-bound error before return. Commented Feb 24, 2018 at 10:25
  • check if (counter > data.available_slots.length) then set counter to default again Commented Feb 24, 2018 at 10:27
  • @javed The length of JSONdata is 7 i.e data.available_slots[0].date to data.available_slots[6] so when the counter reaches 6 it should not increment further and if counter gets decremented then it should not go below 0 how to handle this. Commented Feb 24, 2018 at 10:32
  • @ladjzero The length of JSONdata is 7 i.e data.available_slots[0].date to data.available_slots[6].date so when the counter reaches 6 it should not increment further and if counter gets decremented then it should not go below 0 how to handle this Commented Feb 24, 2018 at 10:32
  • I think it is not a react question. You can minify your question. Let count = (count + length) % length before return. Commented Feb 24, 2018 at 10:44

4 Answers 4

2

Put the check on the counter value before incrementing it's value. Like this:

increment(){
    if(this.state.counter < 6)
        this.setState({
            counter: this.state.counter + 1
        });
}

Or

increment(){
    this.setState(prevState => ({
        counter: prevState.counter < 6? (prevState.counter+1): prevState.counter
    }));
}
Sign up to request clarification or add additional context in comments.

4 Comments

why it cannot be < 7 and why < 6 ? As we want to iterate between 0 ,1,2,3,4,5,6 we want to include 6.
<6 because when value will be 5, it will get incremented to 6 (6 will get included) but after 6 (6 < 6 => will be false) value will not get incremented, but if you use <7, 7 will get included and you will get same error :)
I suggest using data.available_slots.length - 1 instead of a hardcoded 6 value, so you don't have to update that hardcoded value if and when your data changes.
@TimNovis dude why you are commenting on my answer, comment on your answer op will get the notification :P
2
increment(){
    this.setState({
      counter: this.state.counter == data.available_slots.length ? 0 :  this.state.counter + 1
    });
  }

Comments

1

From what I gather, you're trying to prevent this error from showing. A simple way you could fix this is by disabling the "plus" button if there are no more dates in your data file.

For example, in your render function you could do something like this:

render() {
    const maxDateIndex = data.available_slots.length - 1;
    return (
      <div>
        <div id="center">
          <label for="name">Pick a Date </label>
          <button
            disabled={this.state.counter >= maxDateIndex}
            type="button"
            className="btn btn-success"
            id="plus"
            onClick={this.increment.bind(this)}
          >
            +
          </button>
          <input
            type="text"
            id="date"
            value={data.available_slots[this.state.counter].date}
          />
          <button
            type="button"
            className="btn btn-danger"
            id="minus"
            onClick={this.decrement.bind(this)}
          >
            -
          </button>
        </div>
      </div>
    );
  }

Comments

1

Just wanted to mention, that for increments with resets, this works very well:

this.setState({
   counter: (this.state.counter + 1) % data.available_slots.length
})

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.