Несколько компонентов для получения одного значения с Formik - PullRequest
0 голосов
/ 28 февраля 2019

У меня есть 3 <select> компоненты.В первом компоненте у меня есть дни, во втором месяцы, а в третьем - годы.Эти компоненты действуют как одно средство выбора даты.Я попытался обернуть с помощью Formik connect и использовать setFieldValue и setFieldError, но ошибка исчезает после того, как я отредактирую другой компонент в этой форме.

Как решить эту проблему, чтобы ошибка оставалась постоянной.Как я видел, это поведение известно .

class DateField extends Component {
  constructor(props) {
    super(props);
    const value = props.value;
    this.state = {
      day: moment.utc(value).date(),
      month: moment.utc(value).month(),
      year: moment.utc(value).year(),
    };
  }

  handleChange = e => {
    const stateProp = e.target.name.split('.').pop();

    this.setState(
      {
        [stateProp]: e.target.value,
      },
      () => {
        const { formik } = this.props;
        const date = this.dateFromState();
        const error = this.props.validate(date);
        formik.setFieldValue(this.props.name, date, false);
        formik.setFieldError(this.props.name, error);
      }
    );
  };

  handleBlur = () => {
    const { formik } = this.props;
    const date = this.dateFromState();
    const error = this.props.validate(date);
    formik.setFieldTouched(this.props.name, true, false);
    formik.setFieldError(this.props.name, error);
  };

  dateFromState() {
    // returns date constructed from the state
  }

  render() {
    const { formik, name } = this.props;
    const error = getValueByPath(formik.errors, name);

    return (
      <div className="form-group">
        <label>{this.props.label}</label>
        <select
          name={`${this.props.name}.day`}
          value={this.state.day}
          onChange={this.handleChange}
          onBlur={this.handleBlur}
        >
          {
            // options for days
          }
        </select>
        <select
          name={`${this.props.name}.month`}
          value={this.state.month}
          onChange={this.handleChange}
          onBlur={this.handleBlur}
        >
          {
            // options for months
          }
        </select>
        <select
          name={`${this.props.name}.year`}
          value={this.state.year}
          onChange={this.handleChange}
          onBlur={this.handleBlur}
        >
          {
            // options for years
          }
        </select>
        {error && (
          <div className="validation-message">
            <span>{error}</span>
          </div>
        )}
      </div>
    );
  }
}

const getValueByPath = (obj, path) => path.split('.').reduce((o, i) => o && o[i], obj);

export default connect(DateField);

1 Ответ

0 голосов
/ 05 марта 2019

Мой совет - отсоединить компонент от formik, пусть он предоставит дату и обработает изменения соответствующим образом.форма, в которой вы используете это, может затем определить, является ли предоставленная дата действительной или нет, и передать ошибку контролируемому компоненту, чтобы показать, пока дата не будет действительной.Это также отлично подходит для повторного использования.

const DatePicker = ({ name, value, error, onChange, onBlur }) => {
  const today = new Date(value);  
  const [day, setDay] = useState(today.getUTCDay());
  const [month, setMonth] = useState(today.getUTCMonth());
  const [year, setYear] = useState(today.getUTCYear());

  useEffect() => {
   const newDate = new Date([year, month, day]);
   const target = { name, value: newDate };

   onChange({ target });
  }, [day, month, year]);

  return (
    //do your JSX here;
  );
}
...