Art*_*hur 9 html javascript reactjs formik
GitHub discussion about this issue - https://github.com/jaredpalmer/formik/issues/529
I passed formik values to a function that is called in <Field/>'s onChange but when I type in the <Field/>, the last character does not fall into the function.
CodeSandbox - link
Screenshot:
Minimal Code Instance:
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"));
Run Code Online (Sandbox Code Playgroud)
Sed*_*der 10
我不熟悉 formik,我只是快速浏览了一下实现。但这是我对这个问题的两分钱。
为什么每次调用后值都没有更新?
您试图在重新渲染发生之前获取值,并且您拥有的值始终是旧值,因为组件尚未更新。
要验证尝试console.log(values.fields[0]);在 getValue 定义之前添加App 组件。
为什么调用会在重新渲染之前发生?
该onChange实现将触发handleChange它是一个记忆化的函数调用,如果您具有相同的值但您更改了该值,则不会触发该调用。
handleChange如果executeChange值不同,则将被触发,并executeChange根据setFieldValue或 进行记忆state.values。
setFieldValue是一个事件回调,只在每次渲染后更新 ref。那来自formik docs // we copy a ref to the callback scoped to the current state/props on each render,在您的情况下还没有发生- useEventCallback-。
一旦状态被操作更新,你的组件就会被更新,但你的函数还没有被调用。
setFieldValue会尝试验证输入,并返回一个承诺和气泡,高达executeChange和handleChange它对待,作为一个低优先级的,所以它不是一个阻塞调用。
一个快速的解决方案可能是使用onKeyUp而不是onChange我认为这将绕过useCallback并实际更新具有更高优先级调用的组件
function App({ values, setFieldValue }) {
console.log("Rerendering",values.fields[0])
//------ HERE ----------
const getValues = () => console.log(values.fields[0]);
//----------------------
return (
<div className="formik-wrapper">
<Form>
<FieldArray
name="fields"
render={() => (
<Field
type="text"
name="fields.0"
placeholder="Write something"
onKeyUp={e => {
setFieldValue("fields.0", e.target.value);
getValues();
}}
/>
)}
/>
</Form>
</div>
);
}
Run Code Online (Sandbox Code Playgroud)
我希望这可以有所帮助,或者至少可以带来一些帮助。
该答案基于Formik v1.5.7
您正在尝试values在调用后立即在代码中获取过时的值,该值在setFieldValue内部正在执行异步操作,因此您不能期望值在(调用)返回后立即被更改。因此,当您尝试从values当前(运行)渲染周期中注销值时,会得到状态对象。
当valuesdo更改时,Formik重新呈现将具有您想要获得的期望值的形式。
我在您的示例中上移了代码以进行解释。
这是更新的代码链接。
由于此问题是在我回答后更新的,因此我将对此特定的GitHub问题发表评论。问题出在增强开发请求中,注释中的解决方案在您的示例中不起作用,因为values仍然是“ OLD”值。
这是async await在这种情况下解决方案不起作用的原因:
onChange={async e => {
await setFieldValue("fields.0", e.target.value);
getValues(values);
}}
Run Code Online (Sandbox Code Playgroud)
上面的代码在执行awaits函数调用时单击事件,setFieldValue并在内部设置状态,该状态是放置在执行堆栈中的异步操作。呼叫返回和console.log日志values恰好是现有的渲染周期values。
希望能澄清。
如果我正确理解您的问题,您需要一种可靠的方法来获取 Formik 值的最新状态,在设置字段的值并基于此“新”值集触发另一个方法/函数/事件之后。这里明显的障碍是这setFieldValue()是一种内部使用的异步方法,setState()因此没有直接的方法以您描述/预期的方式实现这一点。
componentDidUpdate有用的一种方法是使用(或任何其他类似的 React Lifecycle 方法)并监听 props 的变化。this.props.valuescomponentDidUpdate,您只需要将之前的 props 与新的 props 进行比较以检查是否发生了某些变化。这是一个最小的代码来显示我的意思。
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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助。
| 归档时间: |
|
| 查看次数: |
2053 次 |
| 最近记录: |