使用formik进行react-boostrap-typeahead重置

时间:2018-07-05 20:47:08

标签: reactjs formik react-bootstrap-typeahead

我正在使用来自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属性。我可以设置默认的INITIAL值。但是我遇到的问题是,当我单击按钮处理handle时,formik会执行其操作并将值重置回Office 1,但是AsynchTypeahead无法手动将值传递回该方法。因此它不会改变。我看到有一个selected道具可以使用,但是当我尝试使用它时它就会炸毁。 任何输入都会是gerat

更新:

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

2 个答案:

答案 0 :(得分:0)

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

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字段周围)提取到单独的组件中。

Reference to API.

答案 1 :(得分:0)

在我的情况下,我不得不选择一个更简单的解决方案,方法是在这里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>
    )
}
相关问题