我正在尝试以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进行操作的说明。
答案 0 :(得分:7)
更新为Dani Vijay's answer。
这使用了Formik v2中的useField
和useFormikContext
,以简化组件的使用。
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);
}}
/>
);
};
用法(有关完整的表单声明,请参见Dani的答案):
...
<DatePicker name="date" />
...
答案 1 :(得分:0)
答案 2 :(得分:0)
我从您的代码中看到的是DatePicker不在Formik内部。在React.js中,我们总是创建可重用的组件,因此保持代码干净且易于测试。为了能够在代码中使用DatePicker,请创建一个单独的文件,为Datepicker编写代码,并将其呈现为Field的一部分。这是您应该如何实施。
//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;
答案 3 :(得分: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" />
答案 4 :(得分:0)
更新到Dani Vijay and ToolmakerSteve's answers:
直接使用 setValue
而不是 setFieldValue
。基于@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);
}}
/>
);
};
注意:此方法允许您将 Formik 与 react-datepicker
一起使用,但它也适用于其他 UI 库,例如 Material-UI 和 Ant Design。