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

Created on 25 May 2018  路  5Comments  路  Source: airbnb/react-dates

Hey, I'm trying to use react-dates for the first time, and I'm getting this error.

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

Yes, I've included import react-dates/initialize at the top of my component.

Below is what I've got:

import 'react-dates/initialize';
// import 'react-dates/lib/css/_datepicker.css';

import React from 'react';
import _ from 'lodash';
import PropTypes from 'prop-types';
import moment from 'moment';
import DateRangePicker from 'react-dates';

import { getLastWeekDay } from '../utils/Helpers';
import { Button } from 'react-bootstrap';


class DateRangeInput extends React.Component {

    constructor(props) {
        super(props);

        this.state = {
            focused: null
        };
    }

    onDatesChange = (startDate, endDate, label) => {
        if (label !== undefined) {
            alert('custom!');
        }

        this.props.onChange(startDate, endDate);
    };

    renderDatePresets = () => {
        return _.forOwn(this.props.presets, ([start, end], label) => {
            const isSelected = start.isSame(this.props.startDate) && end.isSame(this.props.endDate);
            return (
                <Button
                    onClick={() => this.onDatesChange(start, end, label)}
                    disabled={isSelected}
                >
                    {label}
                </Button>
            )
        });
    };

    render() {

        const {startDate, endDate, onChange} = this.props;

        return (
            <div>
                <DateRangePicker
                    renderCalendarInfo={this.renderDatePresets}
                    onDatesChange={this.onDatesChange}
                    startDate={startDate}
                    endDate={endDate}
                    startDateId="start_date_id"
                    endDateId="end_date_id"
                    focusedInput={this.state.focused}
                    onFocusChange={focused => this.setState({ focused })}
                />
            </div>
        );
    }
}

DateRangeInput.propTypes = {
    startDate: (props, propName) => moment.isMoment(propName),
    endDate: (props, propName) => moment.isMoment(propName),
    dateFormat: PropTypes.string.isRequired,
    presets: PropTypes.shape({
        [PropTypes.string]: PropTypes.arrayOf((propValue, key) => moment.isMoment(propValue[key]))
    }).isRequired,
    onChange: PropTypes.func.isRequired,
};

DateRangeInput.defaultProps = {
    startDate: moment(),
    endDate: moment(),
    dateFormat: 'YYYYMMDD',
    presets: {
        'Today'        : [moment(), moment()],
        'Last week day': [getLastWeekDay(), getLastWeekDay()],
        'Last 7 Days'  : [moment().subtract(6, 'days'), moment()],
        'Last 30 Days' : [moment().subtract(29, 'days'), moment()],
        'This Month'   : [moment().startOf('month'), moment()],
        'Last Month'   : [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')],
        'This Year'    : [moment().startOf('year'), moment()],
        'Last Year'    : [moment().subtract(1, 'year').startOf('year'), moment().subtract(1, 'year').endOf('year')],
    }
};

export default DateRangeInput;

After browsing some other related issues, I'm pulling my hair out.

By the way, do I even need to do import 'react-dates/lib/css/_datepicker.css? Babel complains about an invalid token in the CSS file.

question

Most helpful comment

@ljharb thanks!

Prior to posting this question, I did play around with the import statement, and instead I was getting import errors - I then assumed that the default-export method of importing was the correct thing to do, as I wasn't getting any import errors, merely that cryptic error message, so I didn't think the import was an issue.

It appears that changing the import to { DateRangePicker } and then adding the line 'node_modules/react-dates/index.js': ['DateRangePicker'] to the namedExports section of the commonjs plugin configuration in rollup.config.js has resolved this issue.

I also solved the issue with including the css file by adding the path node_modules/react-dates/lib/css/*.css to the include section of the postcss plugin in my rollup.config.js.

It might be worth documenting the above measures needed to make this work with rollup.

All 5 comments

What does _.forOwn return?

So it seems I misread the documentation in _.forOwn - I assumed that it acted as a map over the keys of an object, whereas it's more of a forEach. Either way, I had tested this code without passing a renderCalendarInfo prop and I was still getting the same issue. I've fixed renderDatePresets now, but I still get the same error with this updated code:

    renderDatePresets = () => {
        return Object.keys(this.props.presets).map(label => {
            const [start, end] = this.props.presets[label];
            const isSelected = start.isSame(this.props.startDate) && end.isSame(this.props.endDate);

            return (
                <Button
                    key={label}
                    onClick={() => this.onDatesChange(start, end, label)}
                    disabled={isSelected}
                >
                    {label}
                </Button>
            );
        });
    };

    render() {

        const {startDate, endDate, onChange} = this.props;

        console.log(this.renderDatePresets());

        return (
            <div>
                <DateRangePicker
                    // renderCalendarInfo={this.renderDatePresets}
                    onDatesChange={this.onDatesChange}
                    startDate={startDate}
                    endDate={endDate}
                    startDateId="start_date_id"
                    endDateId="end_date_id"
                    focusedInput={this.state.focused}
                    onFocusChange={focused => this.setState({ focused })}
                />
            </div>
        );
    }

renderDatePresets now returns an array of 8 buttons - but this is unrelated to the error.

Your import of DateRangePicker is wrong - react-dates doesn鈥檛 have a default exported component.

@ljharb thanks!

Prior to posting this question, I did play around with the import statement, and instead I was getting import errors - I then assumed that the default-export method of importing was the correct thing to do, as I wasn't getting any import errors, merely that cryptic error message, so I didn't think the import was an issue.

It appears that changing the import to { DateRangePicker } and then adding the line 'node_modules/react-dates/index.js': ['DateRangePicker'] to the namedExports section of the commonjs plugin configuration in rollup.config.js has resolved this issue.

I also solved the issue with including the css file by adding the path node_modules/react-dates/lib/css/*.css to the include section of the postcss plugin in my rollup.config.js.

It might be worth documenting the above measures needed to make this work with rollup.

If rollup requires additional measures to work with standard npm ecosystem patterns, then that's something rollup needs to document, not "every single package on npm".

However, it'd be great to clear up the react-dates docs on the CSS file, since that's not a conventional practice like named imports. A PR is welcome!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

AsasinCree picture AsasinCree  路  3Comments

jpollard-cs picture jpollard-cs  路  3Comments

Adam-Pendleton picture Adam-Pendleton  路  3Comments

krissalvador27 picture krissalvador27  路  3Comments

swaritkohli picture swaritkohli  路  3Comments