Source:  Twitter logo

I'm trying to use react-datepicker in a Formik form.

I have:

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


class Fuate extends React.Component {
    state = {
        dueDate: new Date()

    }

<Formik
                initialValues={initialValues}
                validationSchema={Yup.object().shape({
                    title: Yup.string().required("A title is required "),
                })}

                onSubmit={this.handleSubmit}

                render={({ 
                    errors, 
                    status, 
                    touched, 
                    setFieldValue,
                    setFieldTouched, 
                    handleChange, 
                    handleBlur,
                    handleSubmit, 
                    isSubmitting, 
                    dirty, 
                    values 
                }) => {

                return (
                    <div>
            ...

<DatePicker
                                            name={'dueDate'}
                                            value={values['dueDate']}
                                            onChange={e => setFieldValue('dueDate', e)}
                                        />
                                        <DatePicker
                                        style={{ width: 180 }}
                                        date={values.dueDate}
                                        mode="date"
                                        format="YYYY-MM-DD"
                                        minDate={Date.now.toString()}
                                        maxDate="2050-06-01"
                                        confirmBtnText="Confirm"
                                        cancelBtnText="Cancel"
                                        showIcon={false}
                                        customStyles={{
                                            dateInput: {
                                            marginLeft: 0,
                                            borderColor: "#fff"
                                            }
                                        }}
                                        onDateChange={date => setFieldValue("dueDate", date)}
                                        onTouch={setFieldTouched}
                                        />

For both of these options, the form renders, I can select a date on the calendar but it does not appear in the box and the state value is not updated with the selection.

There are no errors in the console, but the warning says:

Starting with v2.0.0-beta.1 date-fns doesn't accept strings as arguments. Please use parseISO to parse strings. See: toDate @ index.js:45

I tried making the initial state:

dueDate: new Date().toISOString(),

but it makes no difference.

I've seen lots of posts about setting this up with Antd's date picker, but can't find instructions for how to do it with react-datepicker.

Update to Dani Vijay's answer.
This uses useField and useFormikContext from Formik v2, to simplify usage of the component.

DatePicker.jsx:

import React from "react";
import { useField, useFormikContext } from "formik";
import DatePicker from "react-datepicker";

export const DatePickerField = ({ ...props }) => {
  const { setFieldValue } = useFormikContext();
  const [field] = useField(props);
  return (
    <DatePicker
      {...field}
      {...props}
      selected={(field.value && new Date(field.value)) || null}
      onChange={val => {
        setFieldValue(field.name, val);
      }}
    />
  );
};

Usage (see Dani's answer for the complete form declaration):

...
<DatePickerField name="date" />
...

Code at codesandbox

60 users liked answer #0dislike answer #060
ToolmakerSteve profile pic
ToolmakerSteve

react-datepicker can used with Formik by utilising setFieldValue,

const DatePickerField = ({ name, value, onChange }) => {
    return (
        <DatePicker
            selected={(value && new Date(value)) || null}
            onChange={val => {
                onChange(name, val);
            }}
        />
    );
};

const App = () => (
    <Formik
        initialValues={{ date: "" }}
        ...
    >
        {props => {
            const {
                values,
                handleSubmit,
                setFieldValue
                ...
            } = props;
            return (
                <form onSubmit={handleSubmit}>
                    <DatePickerField
                        name="date"
                        value={values.date}
                        onChange={setFieldValue}
                    />
                    ...

CodeSandbox demo here

23 users liked answer #1dislike answer #123
Dani Vijay profile pic
Dani Vijay

What I see from your code is DatePicker is not inside of Formik. In React.js we always create reusable components so keep the code clean and easy to test. To be able to use DatePicker in your code, create a separate file, write your code for Datepicker and render it as a component of the Field. here is how you should implement.

//First let's start with structure of Formik.
import PortDate from "./form/PortDate";
//define your components in a different directory. I named it form
const CreateForm = props => (
    <div>
      <Formik
        initialValues={{"your initial values"}}
        validate={your validation function here}
        onSubmit={values => {
          return props.onSubmit(values);
        }}
      >
        {({ isSubmitting }) => (
          <Form>     
            <Field name="startDate" component={DatePicker} label="Start Date" />

            <Field
              name="endDate"
              component={DatePicker}
              label="End Date"
              canBeDisabled={true}
            />

          </Form>
        )}
      </Formik>
    </div>
  );

now in a different component let's implement our Datepicker logic. //Use reactstrap instead of bootstrap when you want to add style

import { FormGroup, Label } from "reactstrap";
class DatePicker extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
        dueDate: new Date(),
      };
      this.handleChange = this.handleChange.bind(this);
    }
    setFieldValueAndTouched(date, touched) {
      const { setFieldValue, setFieldTouched } = this.props.form;
      const { name } = this.props.field;
      setFieldValue(name, date, true); //field,value,shouldValidate
      setFieldTouched(name, touched, true); //field,touched,shouldValidate
    }
    handleChange(date) {

      this.setState(() => ({ dateValue: date }));
      this.setFieldValueAndTouched(date, true);    }

    render() {
      const { dueDate } = this.state;
      const {
        label,
        field,
        form: { touched, errors },
      } = this.props;
      // field and form props are passed to this component automatically because we render this inside component of the Field. 
      return (
        <FormGroup>
          <Label>{label}</Label>
          <div className="input-group">

              <DatePicker

                selected={dueDate}
                onChange={this.handleChange}
                peekNextMonth
                showMonthDropdown
                showYearDropdown
                maxDate={new Date()}
                dropdownMode="select"
              />

          </div>
        </FormGroup>
      );
    }
  }

  export default DatePicker;
1 users liked answer #2dislike answer #21
Yilmaz profile pic
Yilmaz

Update to Dani Vijay and ToolmakerSteve's answers:

Use setValue directly instead of setFieldValue. Based on @asologor's comment.

import React from "react";
import { useField } from "formik";
import DatePicker from "react-datepicker";

export const DatePickerField = ({ ...props }) => {
  const [field, , { setValue }] = useField(props);
  return (
    <DatePicker
      {...field}
      {...props}
      selected={(field.value && new Date(field.value)) || null}
      onChange={(val) => {
        setValue(val);
      }}
    />
  );
};

Note: This method lets you to use Formik with react-datepicker, but it also works for other UI Libraries like Material-UI and Ant Design too.

1 users liked answer #3dislike answer #31
Logicism profile pic
Logicism
const formik = useFormik({
    initialValues: {    
     date:""
    },
    onSubmit: (values) => {
      alert(JSON.stringify(values, null, 2));
    },
  }); 

 <MuiPickersUtilsProvider utils={DateFnsUtils}>
                  <KeyboardDatePicker
                    disableToolbar
                    variant="inline"
                    TextFieldComponent={(params) => {
                      return <TextField className={classes.TextField} 
                       {...params} variant="outlined" />;
                    }}
                    format="dd MMM yyyy"
                    margin="normal"
                    name="installDate"
                    value={formik.values.date}
                    onChange={(newDate) => {

                       //use this here
                      formik.setFieldValue("date", newDate);


                    }}
                    KeyboardButtonProps={{
                      "aria-label": "change date",
                    }}
                  />
                </MuiPickersUtilsProvider>
1 users liked answer #4dislike answer #41
Damian Renz'es profile pic
Damian Renz'es

How to make this to work for the date range picker:

const [startDate, setStartDate] = useState(new Date());
const [endDate, setEndDate] = useState(new Date());
const { setFieldValue } = useFormikContext();
const [field] = useField({ name: name, value: startDate });
const [field2] = useField({ name: name2, value: endDate });

<GroupContainer>
 <DatePicker
    {...field}
    onFocus={() => setFocusStart(true)}
    onCalendarClose={() => setFocusStart(false)}
    selected={(field.value && new Date(field.value)) || null}
    onChange={(val) => {
                    setStartDate(val);
                    setFieldValue(field.name, val);
                }}
    dateFormat="dd.MM.yyyy" 
    selectsStart                            
    minDate={new Date()}                                
            />
</GroupContainer>

<GroupContainer>
  <DatePicker
    {...field2}
    onFocus={() => setFocusEnd(true)}
    onCalendarClose={() => setFocusEnd(false)}          
    selected={(field2.value && new Date(field2.value)) || null}
    onChange={(val) => {
            setEndDate(val);
            setFieldValue(field2.name, val);
                }}
    dateFormat="dd.MM.yyyy"         
    selectsEnd
    minDate={new Date()}        
            />
</GroupContainer>

Then:

<ReactDatePicker name="arrivalDate" name2="departureDate" />
0 users liked answer #5dislike answer #50
sFritsch09 profile pic
sFritsch09

Copyright © 2022 QueryThreads

All content on Query Threads is licensed under the Creative Commons Attribution-ShareAlike 3.0 license (CC BY-SA 3.0).