关于此问题的GitHub讨论-https://github.com/jaredpalmer/formik/issues/529
我将Formik值传递给在<Field/>
的onChange中调用的函数,但是当我键入<Field/>
时,最后一个字符不会落入该函数中。
CodeSandbox -link
屏幕截图:
最小代码实例:
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"));
答案 0 :(得分:2)
我对Formik不熟悉,我只是对实现进行了快速浏览。 但是,这是我在这个问题上的两分钱。
为什么每次调用后值都不会更新?
您正在尝试在重新渲染之前获取值,并且您拥有的值始终是旧值,因为该组件尚未更新。
要进行验证,请尝试在getValue定义之前在App组件中添加aws sns get-topic-attributes --topic-arn "SNS topic ARN"
。
为什么在重新呈现之前进行呼叫?
console.log(values.fields[0]);
实现将触发onChange
,其中是一个记忆化的函数调用,如果您具有相同的值但更改了该值,则不会触发该调用。
handleChange
的值不同并且handleChange
也被记住取决于executeChange
或executeChange
,则会触发 setFieldValue
。
state.values
是事件回调,仅在每次渲染后更新引用。那是来自formik docs setFieldValue
,在您的情况下尚未发生-// we copy a ref to the callback scoped to the current state/props on each render
-。
通过操作更新状态后,您的组件将被更新,但尚未调用您的函数。
useEventCallback
将尝试验证输入并返回一个承诺并冒泡,直到setFieldValue
和executeChange
为止,并将其视为低优先级,因此它不是阻塞调用。
一种快速的解决方案可能是使用handleChange
而不是onKeyUp
,我认为这会绕过onChange
并实际上以更高优先级的调用来更新组件
useCallback
我希望这可以帮助或至少可以帮助您。
答案 1 :(得分:2)
如果我正确理解了您的问题,则需要一种可靠的方法来获取Formik值的最新状态,即在设置字段的值并基于此“新”值集触发另一种方法/函数/事件之后。这里明显的障碍是setFieldValue()
是一种内部使用setState()
的异步方法,因此,没有直接的方法可以按照您描述/预期的方式来实现。
componentDidUpdate
(或任何其他类似的React Lifecycle方法)并监听道具的变化。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);
}}