0

I'm using react-dates for a datepicker that when the user changes the date it updates a prop and that is sent to the backend to be run as a parameter in a query to get specific results for that day from the database. It looks like this:

    class TableComponent extends Component {
    constructor(props) {
    super(props);

    this.columnDefs = columnDefs;
    this.state = {
      isLoading: true,
      showTimeoutPopup: false,
      tableData: [],
      currentDate: this.props.currentDate
     };
    }

    componentDidMount() {
       this.fetchData();
     }

    componentDidUpdate(prevProps) {
      if (`${this.props.currentDate}` !== prevProps.currentDate) {
        this.fetchData(this.props.currentDate);
      }
    }

    fetchData() {
      this.setState({
        isLoading: true
      });

    someApi.getData(this.props.currentDate).then(tableData => this.setState({
      tableData: tableData,
      isLoading: false
    }))
      .catch(error => {
        if (error.message === 'timeout') {
          this.setState({
            showTimeoutPopup: true
          });
        } else {
          throw new Error(error.message);
        }
      });
    }

This works when using the date picker to select a date using the UI. When I try to type a date, it crashes because when I enter the first digit, say 1 for the month in 12/23/2019, it sends that 1 in the API request which fails as its not a valid date. However, if I paste in the entire date it will work as it is getting a proper date. Is there a better alternative to componentDidUpdate or a better way to structure this type of request? I need it to wait until the entire date is entered before it sends the request. I don't necessarily want to have a button click either, I would like it to do this all in the text box of the date picker. If it matters here is the datepicker component:

  class DatePicker extends Component {
    constructor(props) {
      super(props);
      this.state = {
        currentDate: this.props.currentDate,
        focused: false
      };
    }

    componentDidUpdate(prevProps) {
      if (prevProps.currentDate !== this.props.currentDate) {
        this.setState({currentDate: this.props.currentDate});
      }
    }

    render() {
      return (
        <div className="form-group">
          <label className="tuxedo_label">Select or enter a date to view error reports for that 
           day</label>
          <div className="input_feedback">Dates should be in the format MM/DD/YYYY</div>
          <SingleDatePicker
            date={this.state.currentDate}
            id="date_id"
            customInputIcon={
              <i className="icon calendar-o blue">
                <span className="sr-only">open calendar</span>
              </i>
            }
            displayFormat="MM/DD/YYYY"
            numberOfMonths={1}
            isOutsideRange={() => false}
           onDateChange={this.props.onDateChange}
            focused={this.state.focused}
            onFocusChange={({ focused }) => this.setState({ focused: focused })}
          />
        </div>
      );
    }
  }
wjandrea
  • 28,235
  • 9
  • 60
  • 81
  • Add a validator to check if input satisfied Date Type or something in your `componentDidUpdate` condition would be an optional choice. – keikai Dec 23 '19 at 17:30
  • Please don't edit your post to remove everything. If you want it deleted, flag it to a mod. All the contents are still available in the revision history, so I've just restored it. – wjandrea Jan 24 '20 at 22:44

1 Answers1

0

use moment to validate

npm install moment --save

import moment from 'moment';

componentDidUpdate(prevProps) {
      if (`${this.props.currentDate}` !== prevProps.currentDate && moment(this.props.currentDate).isValid()) {
          this.fetchData(this.props.currentDate);
      }
}
Babak Yaghoobi
  • 1,892
  • 9
  • 18