Redux-form-material-ui: DatePicker: Invalid prop value of type string

Created on 2 Sep 2016  路  28Comments  路  Source: erikras/redux-form-material-ui

This is how I'm using the DatePicker component:
<Field name="date" component={DatePicker} hintText="Pick a Date" />

Getting this error:

Failed prop type: Invalid prop `value` of type `string` supplied to `DatePicker`, expected `object`.
    in DatePicker (created by ReduxFormMaterialUIDatePicker)

Most helpful comment

@rafaelhz solution works for me. And it makes sense as the Datepicker component need value as an object. Please see my renderDatePicker function:

const renderDatePicker = ({ input, defaultValue, meta: { touched, error } }) => (
    <DatePicker 
        errorText = {touched && error} 
        {...input}
        value = {input.value !== ''? new Date(input.value) : null}
        onChange = {(event, value) => {console.log(value); input.onChange(value)}} />
)

And insert DatePicker in a Field component

<Field name="checkin_date" component={renderDatePicker} hintText="Checkin Date" autoOk={true} />

All 28 comments

Getting this same warning

In the example here the field has defaultValue={null}. This would probably fix the issue, except it looks like Field no longer accepts the defaultValue prop since a couple of weeks ago: https://github.com/erikras/redux-form/pull/1593

Yea, that doesn't fix it. Should be a simple fix though...

the warning is related to the value property, not the defaultValue. The ReduxFormMaterialUIDatePicker is setting an empty string when the initial value of the Redux Form is not defined, the value should be an object.

I fixed it including a verification in the ReduxFormMaterialUIDatePicker:
value: inputProps.value !== '' ? inputProps.value : null

export default createComponent(
  DatePicker,
  ({
    input: {
      onBlur, // eslint-disable-line no-unused-vars
      onChange,
      ...inputProps
    },
    ...props
  }) => ({
    ...inputProps,
    ...mapError(props),
    onChange: (event, value) => onChange(value),
    value: inputProps.value !== '' ? inputProps.value : null
  })
)

I am getting this warning too and making thedefaultValue={null} doesn't resolve things for me. I assume the material-ui example is now generating these warnings too?

any news on this?

That's because the Material UI TimePicker and DatePicker components now uses a Date object.

redux-form seems to convert any Date object passed as an initial value to a string, and the same goes for null.

One way around it would be

const mapError = ({ meta: { touched, error } = {}, input: { ...inputProps }, ...props }, errorProp = 'errorText') =>
  touched && error ? { ...props, ...inputProps, [errorProp]: error } : { ...inputProps, ...props }

function createComponent(MaterialUIComponent, mapProps) {
  class InputComponent extends Component {
    getRenderedComponent() {
      return this.refs.component;
    }

    render() {
      return createElement(MaterialUIComponent, {
        ...mapProps(this.props),
        ref: 'component',
      });
    }
  }
  InputComponent.displayName = `${MaterialUIComponent.name}`;
  return InputComponent;
}

export default createComponent(TimePicker,
  ({
    input: {
      onBlur,
      onChange,
      value,
      ...inputProps,
    },
    ...props,
  }) => {
    return {
      ...inputProps,
      ...mapError(props),
      value: value && new Date(value) || null,  // THIS IS THE WORKAROUND, we convert back to Date object
      onChange: (event, _value) => onChange(_value),
    };
  }
);

Not sure though if this should be added to the codebase, the issue seems deeper than that but I have not dug into redux-form really, maybe there is a reason for that conversion to an empty string. @erikras any input on this?

@rafaelhz solution works for me. And it makes sense as the Datepicker component need value as an object. Please see my renderDatePicker function:

const renderDatePicker = ({ input, defaultValue, meta: { touched, error } }) => (
    <DatePicker 
        errorText = {touched && error} 
        {...input}
        value = {input.value !== ''? new Date(input.value) : null}
        onChange = {(event, value) => {console.log(value); input.onChange(value)}} />
)

And insert DatePicker in a Field component

<Field name="checkin_date" component={renderDatePicker} hintText="Checkin Date" autoOk={true} />

@ducminhn no longer Invalid prop value of type string with this solution,
but "Uncaught TypeError: Cannot read property 'onBlur' of undefined".

https://github.com/erikras/redux-form/blob/master/src/createFieldProps.js#L53 This is where the empty string comes from. Here's the change, which also adjusted the documentation: https://github.com/erikras/redux-form/commit/345f46905c4e1bf38b5615b84cb58d507412f323

Providing initialValues is certainly not an option here. In my case, the error occurs before the proper initialValues are available.

To me, filtering out the special value "" and replacing it back with null seems legitimate (i.e. @rafaelhz solution). Though I'm not sure about @erikras reason he put in the Field documentation: Would that make the DatePicker an uncontrolled component? That's certainly not desirable, but what else would you pass to a DatePicker to make it controlled, but empty?
// EDIT: null doesn't seem to make the component uncontrolled: https://github.com/callemall/material-ui/blob/master/src/DatePicker/DatePicker.js#L234

Another possibility could be to use the "format" parameter (https://github.com/erikras/redux-form/blob/master/src/createFieldProps.js#L67), though that would prevent the user from setting their own function there.

@tchri You are probably still importing DatePicker from _redux-form-material-ui_ where you should be importing it from _material-ui/DatePicker_ for this fix to work.

@ducminhn, Thank you, it works for me.

@ducminhn, I have this error too:
"Uncaught TypeError: Cannot read property 'onBlur' of undefined".

@kyrisu Thank you, it works now!

@n0ne, kyrisu gave the answer.

@Philipp91 Thanks!

How I fix it:

  1. import DatePicker from redux-form-material-ui, not from Material-ui
  2. Field component={DatePicker} format={(value, name) => value === '' ? null : value}

Good luck!

@restmount thanks for that, solved it for me as well.

I ended up doing this to solve my date issues: format={value => value ? new Date(value) : null} I am using Firebase as a back end so I end up having to convert to and from string anyway. Would be nice to update the component in this lib to check types

Does anyone have a full example of this working ( @cif @kyrisu @Philipp91 ) -- have tried all combinations of above and still can't get it jiving. Would be mucho appreciated!

@megkadams the DatePicker is expecting a javascript Date object as the prop. To see what you are passing it, do this:

<Field 
  name="expiresOn" 
  component={DatePicker} 
  format={(value, name) => { 
    console.log('value being passed:', value);
    console.log('is of type:', typeof value);
    return value === '' ? null : value 
}} />

You will then need to use the value being passed to construct a new Date instance (or null), in my example I'm using new Date(isoStringFmt) for this purpose

You can now pass a format={null} to ensure that your Date value is not converted to a string.

adding format null did not worked for me, but trying to satisfy PropType by pssing an object did for me.
Just add value={input.value !== '' ? input.value : {}} to your DatePicker props.

@restmount, @cif Thanks!


restmount comment

import DatePicker from redux-form-material-ui, not from Material-ui
Field component={DatePicker} format={(value, name) => value === '' ? null : value}

cif comment

<Field 
    name="expiresOn" 
    component={DatePicker} 
    format={(value, name) => { 
    console.log('value being passed:', value);
    console.log('is of type:', typeof value);
    return value === '' ? null : value 
}} />

so i edit my component like this.

import {  DatePicker } from 'redux-form-material-ui`;
<Field
    name="planDetails.startDate"
    component={DatePicker}
    container="inline"
    autoOk={true}
    format={(value) => value === '' ? null : new Date(value)}
    floatingLabelText="Plan Start" 
    hintText="Plan Start"/>

With values restored from localStorage I did faced the issue that it could whether be a String or a date:

<Field
  name="date"
  component={DatePicker}
  format={(value, name) => value === '' ? null : (typeof value === 'string') ? new Date(value) : value}
/>

@michabu - I think you saved me another hour for this, well caught!

I've tried every pasted example given by everyone and not a single one seems to work =/

Simple and easy solution use moment() instead of new Date() , remember to import moment from "moment";


constructor(props) {
super(props);
this.state = {
date: moment(),
};
}

selected={this.state.date}
onChange={date =>
this.setState({
date: date
})
}
/>

I know this is an old one but what worked for me was setting propTypes like this:

DatePicker.propTypes = {
  date: PropTypes.instanceOf(Date).isRequired,
};
Was this page helpful?
0 / 5 - 0 ratings

Related issues

jeongsd picture jeongsd  路  7Comments

dealvz picture dealvz  路  4Comments

ilyador picture ilyador  路  4Comments

aikidoshi picture aikidoshi  路  5Comments

j18ter picture j18ter  路  3Comments