价值观Formik问题

时间:2019-06-15 19:19:48

标签: javascript html reactjs formik

  

关于此问题的GitHub讨论-https://github.com/jaredpalmer/formik/issues/529

我将Formik值传递给在<Field/>的onChange中调用的函数,但是当我键入<Field/>时,最后一个字符不会落入该函数中。

CodeSandbox -link

屏幕截图

enter image description here

最小代码实例

import React from "react";
import ReactDOM from "react-dom";
import { Formik, Form, Field, FieldArray } from "formik";

function App() {
  //------ HERE ----------
  const getValues = values => console.log(values.fields[0]);
  //----------------------
  return (
    <>
      <Formik
        initialValues={{ fields: [""] }}
        onSubmit={(values, actions) => {
          actions.setSubmitting(false);
          console.log(values);
          return false;
        }}
        render={({ setFieldValue, values }) => (
          <Form>
            <FieldArray
              name="fields"
              render={() => (
                <Field
                  type="text"
                  name="fields.0"
                  placeholder="Write something"
                  onChange={e => {
                    setFieldValue("fields.0", e.target.value);
                    //---------------
                    getValues(values);
                    //---------------
                  }}
                />
              )}
            />
          </Form>
        )}
      />
    </>
  );
}

ReactDOM.render(<App />, document.getElementById("root"));

4 个答案:

答案 0 :(得分:2)

我对Formik不熟悉,我只是对实现进行了快速浏览。 但是,这是我在这个问题上的两分钱。

为什么每次调用后值都不会更新?

您正在尝试在重新渲染之前获取值,并且您拥有的值始终是旧值,因为该组件尚未更新。

要进行验证,请尝试在getValue定义之前在App组件中添加aws sns get-topic-attributes --topic-arn "SNS topic ARN"

为什么在重新呈现之前进行呼叫?

console.log(values.fields[0]);实现将触发onChange,其中是一个记忆化的函数调用,如果您具有相同的值但更改了该值,则不会触发该调用。

如果handleChange的值不同并且handleChange也被记住取决于executeChangeexecuteChange,则会触发

setFieldValue

state.values是事件回调,仅在每次渲染后更新引用。那是来自formik docs setFieldValue,在您的情况下尚未发生-// we copy a ref to the callback scoped to the current state/props on each render-。

通过操作更新状态后,您的组件将被更新,但尚未调用您的函数。

useEventCallback将尝试验证输入并返回一个承诺并冒泡,直到setFieldValueexecuteChange为止,并将其视为低优先级,因此它不是阻塞调用。

一种快速的解决方案可能是使用handleChange而不是onKeyUp,我认为这会绕过onChange并实际上以更高优先级的调用来更新组件

useCallback

我希望这可以帮助或至少可以帮助您。

Check formik implementation

答案 1 :(得分:2)

如果我正确理解了您的问题,则需要一种可靠的方法来获取Formik值的最新状态,即在设置字段的值并基于此“新”值集触发另一种方法/函数/事件之后。这里明显的障碍是setFieldValue()是一种内部使用setState()的异步方法,因此,没有直接的方法可以按照您描述/预期的方式来实现。

  • 我不会推荐github问题(https://github.com/jaredpalmer/formik/issues/529)中提到的变通方法(setTimeout,随机等待以跳过nextTick等),因为它们是不确定的。
  • 对我有用的一种方法是使用componentDidUpdate(或任何其他类似的React Lifecycle方法)并监听道具的变化。
  • Formik在this.props.values处公开React组件的props中的字段值
  • 使用componentDidUpdate时,只需将以前的道具与新道具进行比较,以检查是否有所更改。

这是显示我的意思的最小代码。

const _ = require('lodash');

class Sample extends React.Component {
  componentDidUpdate(prevProps) {
    if(!_.isEqual(prevProps.values, this.props.values)) {
      // At least one of the Formik fields have changed. And this.props.values holds this newest data about of the fields.
      triggerWhateverWithNewValues(this.props.values);
    }
  }
}

希望这会有所帮助。

答案 2 :(得分:1)

您正在尝试在内部进行异步操作的values后立即在代码中获取setFieldValue的陈旧值,因此您不能期望值(调用)返回后立即被更改。因此,当您尝试从values中注销值时,会在当前(运行)渲染周期中得到状态对象。

values发生更改时,Formik重新呈现将要具有您想要获得的期望值的形式。

我在您的示例中上移了代码以对此进行解释。

这是更新的代码链接https://codesandbox.io/s/nc0ys

答案 3 :(得分:0)

调用getValues时,它会获得旧值,因为setFieldValue函数调用未完成(因此值未设置为Field.0)。您可以直接将值传递给函数getValues

const getValues = valueField => console.log(valueField);


onChange={e => {
    setFieldValue("fields.0", e.target.value);
    getValues(e.target.value);
}}

https://codesandbox.io/s/spring-water-ixuuk