Сброс заголовка типа реакции-бустрапа с помощью formik

Вместе с Formik я использую AsyncTypeahead из библиотеки activ-boostrap-typeahead. Обе замечательные маленькие библиотеки. Упрощенная версия моего кода выглядит следующим образом

const SearchFilter = withFormik({ 
  mapPropsToValues: (props) {
    office: someIncomingValue || [{name: 'office1', id: 1}]
  }
})(TheForm)

const TheForm = (props) => {
  const {values, handleReset} = props;
  return (
    <form>
     <AsyncTypeahead 
       defaultSelected={[values.office]}  
       options={...} 
       onChange={...SetNewValue...}
       onSearch={...}/>

      <button onClick={handleReset}
    </form>
  )
}

Используя свойство defaultSelected в AsynchTypeahead. Я могу установить начальное значение по умолчанию. Но у меня возникает проблема, когда я нажимаю кнопку для handleRest, formik делает свое дело и сбрасывает значение обратно в office 1, но AsynchTypeahead не имеет способа вручную передать значение обратно в него. Так что не меняется. Я видел, что есть selected опора доступна, но она просто взрывается, когда я пытаюсь ее использовать. Любой вклад будет герат

ОБНОВИТЬ:

Да, выбрано то, что мне нужно. Мне пришлось добавить свойство onInputChange, чтобы сохранить родителя в синхронизации с тем, что печаталось.

1 ответ

У меня такой же вопрос.
Я придумал это решение:

import { Formik } from "formik";
import * as Yup from "yup";
import { Typeahead } from 'react-bootstrap-typeahead';

const AddCheckSchema = Yup.object().shape({
  title: Yup.string()
      .min(2, 'Too Short!')
      .max(50, 'Too Long!')
      .required('Required')
});

...

render() {
  const users = [
    { id: 1, fullname: 'User #1' },
    { id: 2, fullname: 'User #2' },
    { id: 3, fullname: 'User #3' },
  ];

  return (
    <Formik
        initialValues={{
          title: '',
          amount: 0,
          actualDate: new Date()
        }}
        validationSchema={AddCheckSchema}
        onSubmit={ this.onSubmit}
    >
      {({
          errors,
          touched,
          handleChange,
          handleBlur,
          handleSubmit,
          setFieldValue,
          setFieldTouched,
      }) => (
          <form onSubmit={handleSubmit}>
            <div className="form-group required">
              <label className="control-label">Title:</label>              

              <Typeahead
                  multiple={false}
                  onChange={(selected) => {
                    const value = (selected.length > 0) ? selected[0].fullname : '';
                    setFieldValue('title', value);
                  }}
                  onInputChange={(text, event) => setFieldValue('title', text)}}
                  onBlur={(e) => setFieldTouched('title', true)}
                  labelKey="fullname"
                  options={users}
              />
              <div className="text-danger">{touched.title && errors.title}</div>
            </div>

            <div className="form-group">
              <button type="submit" className="btn btn-primary btn-lg">Add check</button>
            </div>
          </form>
      )}
    </Formik>
  )
}

Конечно, вы можете извлечь эту сложную логику (вокруг поля Typeahead) в отдельный компонент.

Ссылка на API.

В моем случае мне пришлось выбрать более простое решение, взглянув на этот пример здесь https://ericgio.github.io/react-bootstrap-typeahead/#basic-example

export const SelectSearch = ({name, value, schema, setFieldValue, errors}) => {
    const [singleSelections, setSingleSelections] = useState([]);

    useEffect(() => {
        if (singleSelections.length > 0) {
            setFieldValue(name, singleSelections[0].value)
        }
    }, [singleSelections])

    return (
        <LabeledField name={name} schema={schema}>
            <Typeahead
                id="basic-typeahead-single"
                multiple={false}
                labelKey="label"
                options={schema.choices}
                onChange={setSingleSelections}
                isInvalid={!!errors[name]}
                placeholder="Choose a state..."
                selected={singleSelections}
            />
            <Form.Control.Feedback type="invalid">
                {errors[name]}
            </Form.Control.Feedback>
        </LabeledField>
    )
}

Затем этот компонент можно отобразить в контексте formik, как показано ниже.

const Component = () => {
   
    return (
        <Formik
            initialValues={...}
            validationSchema={AddCheckSchema}
            onSubmit={this.onSubmit}
        >
            {({
                  errors,
                  touched,
                  handleChange,
                  handleBlur,
                  handleSubmit,
                  setFieldValue,
                  setFieldTouched,
              }) => (
                <form onSubmit={handleSubmit}>
                    <div className="form-group required">
                        <label className="control-label">Title:</label>

                        <SelectSearch
                            name={"inputName"}
                            choices={choices}
                            setFieldValue={setFieldValue}
                            errors={errors}
                        />
                    </div>

                    <div className="form-group">
                        <button type="submit" className="btn btn-primary btn-lg">Submit</button>
                    </div>
                </form>
            )}
        </Formik>
    )
}
Другие вопросы по тегам