programing

Formik 양식을 사용한 리액트 날짜 선택기

i4 2023. 4. 1. 08:28
반응형

Formik 양식을 사용한 리액트 날짜 선택기

리액트 데이트 피커를 포믹 형태로 사용하려고 합니다.

다음과 같은 것이 있습니다.

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의 달력 선택기로 이 설정을 하는 것에 대한 게시물은 많이 보았지만 리액트 날짜 선택기로 설정하는 방법에 대한 설명을 찾을 수 없습니다.

대니 비제이의 답변을 업데이트하십시오.
Formik v2를 사용하여 컴포넌트 사용을 단순화합니다.

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 답변 참조):

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

코드 앤 박스에서의 코드

react-datepickersetFieldValue를 사용하여 Formik과 함께 사용할 수 있습니다.

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 데모 여기

Dani VijayToolmakerSteve의 답변 업데이트:

사용하다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그러나 Material-UI Ant Design과 같은 다른 UI 라이브러리에서도 사용할 수 있습니다.

당신의 코드를 보니 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 로직을 구현하겠습니다.//스타일 추가 시 부트스트랩 대신 리액트스트랩 사용

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

날짜 범위 선택기에서 이 작업을 수행하는 방법:

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

언급URL : https://stackoverflow.com/questions/56312372/react-datepicker-with-a-formik-form

반응형