35

我正在尝试以 Formik 形式使用 react-datepicker。

我有:

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}
                                        />

对于这两个选项,表单呈现,我可以在日历上选择一个日期,但它不会出现在框中,并且状态值不会随着选择而更新。

控制台中没有错误,但警告说:

从 v2.0.0-beta.1 开始 date-fns 不接受字符串作为参数。请用于parseISO解析字符串。参见:toDate@index.js:45

我尝试制作初始状态:

dueDate: new Date().toISOString(),

但这没有什么区别。

我看过很多关于使用 Antd 的日期选择器进行设置的帖子,但找不到如何使用 react-datepicker 进行设置的说明。

4

6 回答 6

58

更新Dani Vijay 的回答
这使用useFielduseFormikContext来自 Formik v2,以简化组件的使用。

日期选择器.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);
      }}
    />
  );
};

用法(有关完整的表单声明,请参阅 Dani 的回答):

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

代码沙盒中的代码

于 2019-10-31T20:27:39.747 回答
23

react- datepicker 可以通过利用setFieldValueFormik 一起使用,

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 演示在这里

于 2019-05-27T06:41:49.230 回答
1

更新Dani Vijay 和 ToolmakerSteve 的答案

直接使用setValue而不是setFieldValue. 基于@asologor 的评论

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);
      }}
    />
  );
};

注意:此方法允许您将 Formik 与 一起使用react-datepicker,但它也适用于其他 UI 库,如Material-UIAnt Design

于 2021-07-17T04:09:43.450 回答
1

我从您的代码中看到的是 DatePicker 不在 Formik 内部。在 React.js 中,我们总是创建可重用的组件,以保持代码干净且易于测试。为了能够在您的代码中使用 DatePicker,请创建一个单独的文件,为 Datepicker 编写代码并将其呈现为字段的组件。这是您应该如何实施的方法。

//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>
  );

现在在不同的组件中实现我们的 Datepicker 逻辑。//当你想添加样式时,使用 reactstrap 而不是 bootstrap

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;
于 2019-10-06T15:47:52.103 回答
0

如何使它适用于日期范围选择器:

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>

然后:

<ReactDatePicker name="arrivalDate" name2="departureDate" />
于 2021-05-08T10:49:46.893 回答
0
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>
于 2021-11-24T11:15:43.537 回答