8

Currently trying to use React and Typescript with react-datepicker.

I have a simple setup which I want to test, but I keep getting the following error:

Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object

Below is the file which uses the DatePicker package

import * as React from 'react';
import DatePicker from "react-datepicker";

import "react-datepicker/dist/react-datepicker.css";

interface DateConstructor  {
    startDate: Date;
} 

export class DateSelector extends React.Component<{}, DateConstructor > {
    constructor(props) {
        super(props);
        this.state = {
            startDate: new Date()
        };
    }

    private handleChange(date) {
        this.setState({
            startDate: date
        });
    }

    public render() {
        const { startDate } = this.state;
        return (
            <DatePicker 
                dateFormat="dd-mm-yyyy"
                selected={startDate} 
                onChange={this.handleChange}
            />
        )
    }
}

It seems very strange to me that the DatePicker package needs a string or function?

How to resolve this issue?

Full error below

Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.
invariant
http://localhost:65273/dist/vendor.js?v=OjVxDpV6p_Jfz2P38F_R2lc3pjVsUisUejeIABZq7AE:118:15
ReactCompositeComponentWrapper.instantiateReactComponent
http://localhost:65273/dist/vendor.js?v=OjVxDpV6p_Jfz2P38F_R2lc3pjVsUisUejeIABZq7AE:20273:23
ReactCompositeComponentWrapper.performInitialMount
http://localhost:65273/dist/vendor.js?v=OjVxDpV6p_Jfz2P38F_R2lc3pjVsUisUejeIABZq7AE:29799:22
ReactCompositeComponentWrapper.mountComponent
http://localhost:65273/dist/vendor.js?v=OjVxDpV6p_Jfz2P38F_R2lc3pjVsUisUejeIABZq7AE:29690:21
Object.mountComponent
http://localhost:65273/dist/vendor.js?v=OjVxDpV6p_Jfz2P38F_R2lc3pjVsUisUejeIABZq7AE:12868:35
ReactCompositeComponentWrapper.performInitialMount
http://localhost:65273/dist/vendor.js?v=OjVxDpV6p_Jfz2P38F_R2lc3pjVsUisUejeIABZq7AE:29803:34
ReactCompositeComponentWrapper.mountComponent
http://localhost:65273/dist/vendor.js?v=OjVxDpV6p_Jfz2P38F_R2lc3pjVsUisUejeIABZq7AE:29690:21
Object.mountComponent
http://localhost:65273/dist/vendor.js?v=OjVxDpV6p_Jfz2P38F_R2lc3pjVsUisUejeIABZq7AE:12868:35
ReactCompositeComponentWrapper.performInitialMount
http://localhost:65273/dist/vendor.js?v=OjVxDpV6p_Jfz2P38F_R2lc3pjVsUisUejeIABZq7AE:29803:34
ReactCompositeComponentWrapper.mountComponent
http://localhost:65273/dist/vendor.js?v=OjVxDpV6p_Jfz2P38F_R2lc3pjVsUisUejeIABZq7AE:29690:21

Below is the file where I am trying to render the DateSelector component

import * as React from 'react';
import { RouteComponentProps } from 'react-router';

import { DataOutputSwitch } from './ComponentLibrary/DataOutputSwitch';
import { DatatypeSelector } from './ComponentLibrary/DatatypeSelector';
import { DateSelector } from './ComponentLibrary/DateSelector';


export class ComponentLibrary extends React.Component<RouteComponentProps<{}>, {}> {

    public render() {
        return (
            <div>
                <h1>Pair4Insights Component Library</h1>
                <p>This component demonstrates all separate components.</p>
                <div style={{display: 'flex', flexDirection: 'column'}}>
                    <h3>Data Output Switch</h3>
                    <DataOutputSwitch />
                    <h3>Datattype Selector</h3>
                    <DatatypeSelector datatype="revenue" />
                    <h3>Date Selector</h3>
                    <DateSelector />
                </div>
            </div>
        );
    }
}
Pimmesz
  • 335
  • 2
  • 8
  • 29
  • 1
    Can you share the file in which you are using this function? – Muhammad Zeeshan Jan 14 '20 at 13:41
  • Question updated with full file! – Pimmesz Jan 14 '20 at 13:43
  • 1
    It seems like your `onChange` handler doesn't work correctly. Check if it updates the state, by logging it to the console in `render` method. If it doesn't, use either arrow function or `.bind` in constructor – Oscar Jan 14 '20 at 13:47
  • I've set the `onChange` to `console.log('test')` to test whether it was the function. Still getting the same error. – Pimmesz Jan 14 '20 at 13:51

3 Answers3

4

I plugged this component to a working Typescript React application with minor modifications and it works without any problems. So I suspect this problem is caused by some factor other than this component. Does this error go away if you comment out this component and not import it?

For reference' sake, here's the code:

import * as React from 'react';
import DatePicker from "react-datepicker";

import "react-datepicker/dist/react-datepicker.css";

interface DateConstructor  {
    startDate: Date;
} 

export class DateSelector extends React.Component<{}, DateConstructor> {
    constructor(props) {
        super(props);
        this.state = {
            startDate: new Date()
        };
        this.handleChange = this.handleChange.bind(this);
    }

    private handleChange(date) {
        console.log('date is here!', date);
        this.setState({
            startDate: date
        });
    }

    public render() {
        const { startDate } = this.state;
        return (
            <DatePicker
                dateFormat="dd/MM/yyyy"
                selected={startDate} 
                onChange={this.handleChange}
            />
        )
    }
}

and the import at App.tsx:

import { DateSelector } from './DateSelector';

As you can see, few changes I've made are binding the handleChange function and updating the date formatting (at the question code, it's an incorrect input).

recording-datepicker-gif

I hope this answer have nudged you in the correct direction.

Community
  • 1
  • 1
Enes Kirimi
  • 430
  • 6
  • 12
  • Hi! Yes when I comment out the rendering of the component the error goes away. – Pimmesz Jan 17 '20 at 09:08
  • @Pimmesz Hmm, maybe something wrong with the datepicker package itself in your workplace folder? Have you tried reinstalling everything with `npm ci` (or your preferred package manager equivalent) for example? Outside of that, there are too many possibilities to guess where things can go wrong I think. – Enes Kirimi Jan 17 '20 at 12:42
0

The selected prop expects to get a string as default selected value. You are passing a date object. You can use useState hook to maintain the state like:

import {useState} from "react";

const YourComponent = () => {
   const [date, setDate] = useState("");

   return (
      <DatePicker 
          dateFormat="DD-MM-YYYY"
          selected={date} 
          onChange={date => setDate(date)}
       />
   );
}
Muhammad Zeeshan
  • 4,608
  • 4
  • 15
  • 41
  • Well even giving selected a value of `null` should be possible. Still get the same error. If I give the date transformed to a `string` I also get the error: `Invalid time value`. So selected expects an object. – Pimmesz Jan 14 '20 at 13:49
  • 1
    By saying error stack i assume that you share some line number reference to investigate – Muhammad Zeeshan Jan 14 '20 at 13:58
  • This is the full error I've received. It doesn't say anything about a specific line. That is what makes this issue extra difficult. – Pimmesz Jan 14 '20 at 14:23
  • 1
    Can you show me the import of the `DateSelector` where you are using? – Muhammad Zeeshan Jan 14 '20 at 14:56
  • I've added the file where I try to render the `DateSelector` component in the question. – Pimmesz Jan 14 '20 at 15:05
0

Adding date-picker.d.ts file with:

declare module "react-datepicker";

will solve the issue.