7

I'm using React-Datepicker and MomentJS. But when I want to use Moment for setting a startDate, the value gives Invalid date in the datepickerfield.

When I log the this.state.startDate in the console, the console shows me the following: "startdate: 27-11-2018", this has the format 'DD-MM-YYYY'. This format is also used for the DatePicker component.

import * as React from "react";
import * as ReactDOM from "react-dom";

import DatePicker from "react-datepicker";
import "react-datepicker/dist/react-datepicker.css";
import * as moment from "moment";
import "moment/locale/nl";

export class DateContainer extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      startDate: moment().format('DD-MM-YYYY'),
    };
  }
  render() {
    console.log('startdate:',this.state.startDate);
    return (
        <div className="date-Filter">
          <div className="date-Filter-Title">Release Date</div>
          <DatePicker
            onChange={this.handleStartDate}
            selected={this.state.startDate}
            dateFormat="DD-MM-YYYY"
            isClearable={true}
            placeholderText="Select a date other than today or yesterday"
            fixedHeight={true}
            tetherConstraints={ [] }
            locale="nl"
            popperPlacement="right-start"
            popperModifiers={{
             flip: {
               enabled: false
             },
             preventOverflow: {
               enabled: true,
               escapeWithReference: false
             }
           }}
           selectsStart
           startDate={this.state.startDate}
           className="startDate"
           showMonthDropdown
           showYearDropdown
          />
        </div>
    );
  }
}

Can someone explain to me why it is showing invalid date in browser.

My Dependencies:

  "dependencies": {
    "moment": "^2.22.2",
    "react": "^16.6.0",
    "react-datepicker": "^2.0.0",
    "react-dom": "^16.6.0",
    "sass-loader": "^7.1.0",
    "searchkit": "^2.3.1-alpha.4"
  },
Elvira
  • 1,410
  • 5
  • 23
  • 50

4 Answers4

7

Use startDate: moment().toDate().

.format('DD-MM-YYYY') returns a string, while the selected prop of the DatePicker react component requires a Date object.

3

From Hacker0x01 - "Up until version 1.8.0, this package was using Moment.js. Starting v2.0.0, we switched to using native Date objects to reduce the size of the package. If you're switching from 1.8.0 to 2.0.0 or higher, please see the updated example above of check out the examples site for up to date examples."

https://github.com/Hacker0x01/react-datepicker

I am having a similar problem. I am going to try and turn the native Date into a moment after react-datepicker has done it's thing.

Lance Crowder
  • 33
  • 1
  • 6
  • I handled it by setting the start date to a moment and then turned it into a native date that react-datepicker can understand. `this.state = { startDate: moment().todate, };` Then I wrapped the result from the event handler in a moment. `startDate={moment(this.state.startDate)}` hope this helps – Lance Crowder Apr 18 '19 at 16:03
1

@Elvira, i met the same challenge when using react-datepicker@2.0.0. It is critical to follow any 3rd party packages that you make use of. The issue of modules as popularized by ES6 deemed moment.js an extra baggage in react-datepicker since moment.js is an all-in-one package i.e. import moment from 'moment';

The concept of modules enables us to make objects, functions, classes or variables available to the outside world by simply exporting them and then importing them where needed in other files.

Starting with react-datepicker@2.0.0, moment.js was removed as a dependency and the team started using the native javascript Date object paired with date-fns for all date functionality within the datepicker. Inspect propTypes of the react-datepicker calendar component, and you will notice that all dates are declared to be PropTypes.instanceOf(Date).

Solution: Stick to using the native JavaScript Date object. After a user selects a date from your calendar (read: react-datepicker), you can always convert that date object using moment.js to whatever format.

export class DateContainer extends React.Component {
  constructor(props) {
    super(props);
    // Used 'started' to avoid name conflicts, and return date object
    this.state = { started: new Date(), };
  }
  render() {
    const { started } = this.state
    return (
      // other jsx...
      <DatePicker
        // other props...
        selected={started}
        startDate={started}
      />
    );
  }
}

Below is how i went about dealing with this situation: Environment: react@16.9.0, react-redux@7.1.1, react-datepicker@2.0.0, yup@0.27.0 and Formik@1.5.8 (handling forms in react, made easy).

// stateless component
const InputForm = ({
  // other destructered props...
  dispatch = f => f
}) => {
  const values = {
    // initial state
  }

  return (
    <Formik
      // other props...
      onSubmit={
        async (values) => {
          // Here is my solution...
          // convert date object from react-datepicker using moment.js,
          // before i dispatch my state object.
          const userData = {
            ...values,
            start_date: moment(values.start_date).format('YYYY-MM-DD')
          }
          await dispatch(someAction(userData));
          // ...
        }
      }
    />
  )
};

export default connect()(InputForm);
MwamiTovi
  • 2,425
  • 17
  • 25
  • Using `date-fns`? Do this `import { format } from 'date-fns` and assign `start-date: format(values.join_date, 'yyyy-MM-dd')`. It works just fine. – MwamiTovi Nov 09 '19 at 12:34
-3

Instead of using moment in this.state use it in the setState.. that worked for me

constructor(props) {
    super(props);
    this.state = {
      startDate: new Date(),
   }



handleDateChange = date => {
    this.setState({
      startDate: moment(date).format('DD-MM-YYYY')
    });
  };

ChrisR
  • 3,922
  • 1
  • 14
  • 24