3

我正在使用 react-boostrap-typeahead 库中的 AsyncTypeahead 和 Formik。两个很棒的小图书馆。我的代码的简化版本如下所示

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

通过使用 AsynchTypeahead 上的 defaultSelected 属性。我可以设置一个默认的初始值。但是我遇到的问题是当我单击按钮来处理休息时,formik 会执行它的操作并将值重置回办公室 1,但是 AsynchTypeahead 没有手动将值传递回其中的方法。所以它不会改变。我看到有一个selected可用的道具,但是当我尝试使用它时它就会爆炸。任何输入都会很好

更新:

是的,选择的是我需要的。我必须添加一个 onInputChange 属性以使父级与输入的内容保持同步。

4

2 回答 2

4

我有同样的问题。
我想出了这个解决方案:

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。

于 2018-10-21T21:27:56.357 回答
1

在我的情况下,我必须通过在此处查看此示例来选择更简单的解决方案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>
    )
}
于 2020-11-12T21:48:35.423 回答