在 React with Formik 中,我如何构建一个搜索栏来检测输入值以呈现按钮?

In React with Formik how can I build a search bar that will detect input value to render the buttons?

Formik 和 React 的新手我构建了一个搜索组件,我在传递输入值和根据输入长度呈现按钮时遇到问题。

给定组件:

const SearchForm = ({ index, store }) => {
  const [input, setInput] = useState('')
  const [disable, setDisable] = useState(true)

  const [query, setQuery] = useState(null)
  const results = useLunr(query, index, store)
  const renderResult = results.length > 0 || query !== null ? true : false

  useEffect(() => {
    if (input.length >= 3) setDisable(false)
    console.log('input detected', input)
  }, [input])

  const onReset = e => {
    setInput('')
    setDisable(true)
  }

  return (
    <>
      <Formik
        initialValues={{ query: '' }}
        onSubmit={(values, { setSubmitting }) => {
          setInput('')
          setDisable(true)

          setQuery(values.query)
          setSubmitting(false)
        }}
      >
        <Form className="mb-5">
          <div className="form-group has-feedback has-clear">
            <Field
              className="form-control"
              name="query"
              placeholder="Search . . . . ."
              onChange={e => setInput(e.currentTarget.value)}
              value={input}
            />
          </div>
          <div className="row">
            <div className="col-12">
              <div className="text-right">
                <button type="submit" className="btn btn-primary mr-1" disabled={disable}>
                  Submit
                </button>
                <button
                  type="reset"
                  className="btn btn-primary"
                  value="Reset"
                  disabled={disable}
                  onClick={onReset}
                >
                  <IoClose />
                </button>
              </div>
            </div>
          </div>
        </Form>
      </Formik>

      {renderResult && <SearchResults query={query} posts={results} />}
    </>
  )
}

我已经确定了我的问题所在,但在尝试解决时遇到困难:

<Field
  className="form-control"
  name="query"
  placeholder="Search . . . . ."
  onChange={e => setInput(e.currentTarget.value)}
  value={input}
/>

来自 Field 的 onChangevalue 是我的问题。如果我拥有 submit 上发布的所有内容,则传递的查询不存在。如果我删除了提交按钮的两个硬编码 true,我的查询就会工作。

研究

在 Formik 中,我如何构建一个搜索栏来检测输入值以呈现按钮?

您需要利用作为 Formik 组件的一部分提供的道具。他们的文档显示 simple example 与您需要的类似:

<Formik
  initialValues={{ query: '' }}
  onSubmit={(values, { setSubmitting }) => {
    setInput('')
    otherStuff()
  }}
>
  {formikProps => (
    <Form className="mb-5">
      <div className="form-group has-feedback has-clear">
        <Field
          name="query"
          onChange={formikProps.handleChange}
          value={formikProps.values.query}
        />
      </div>
      <button 
        type="submit" 
        disabled={!formikProps.values.query}
      >
        Submit
      </button>
      <button
        type="reset"
        disabled={!formikProps.values.query}
        onClick={formikProps.resetForm}
      >
    </Form>
    {/* ... more stuff ... */}
  )}
</Formik>

您使用此渲染道具模式将 formiks 道具拉出来(我通常称它们为 formikProps,但您可以随意称呼它们),然后它可以访问您需要的一切。您无需使用 inputsetInputdisablesetDisable 变量,只需引用 formikProps 中的内容即可。例如,如果你想禁用提交按钮,你可以只说disable={!formikProps.values.query},意思是如果表单中的query值为空字符串,你不能提交表单。

至于 onChange,只要您为字段提供正确的 name,因为它对应于 initialValues 对象中的 属性,formikProps.handleChange 将知道如何为您正确更新该值。使用 formikProps.values.whatever 作为字段的 value,您的组件将自动读取这些更新。 namevalueonChange 的组合,全部通过 formikProps 处理,使表单处理变得容易。

Formik 有大量非常有用的预建功能来为您处理这个问题。我建议在他们的文档站点上闲逛,您会发现自己只需编写很少的代码来处理这些常见的表单行为。