javascript - 如何在 Formik 'onSubmit' 函数中正确地 'useState'?
问题描述
我在 Next.js 应用程序中使用 Formik,但遇到了一个不知道如何解决的问题。我的提交Button
是一个接受showSpinner
道具的组件。如果为 true -> 按钮被禁用,并且显示按钮中的加载微调器。showSpinner
价值取决于loading
来自useState
钩子。这是一个相关的代码:
export default function register() {
const [loading, setLoading] = useState(false)
return (
<>
<Layout>
<div className={styles.registerContainer}>
<div className={styles.registerFormContainer}>
<h1 className={styles.registerHeader}>Sign Up</h1>
<Formik
initialValues={{
email: '',
password: '',
passwordConfirm: '',
acceptedTerms: false
}}
onSubmit={
(values, { setSubmitting }) => {
console.log(loading)
// here loading == false as expected
setLoading(true)
console.log(loading)
// here loading == false even though i set it to true
initFirebase()
firebase.auth().createUserWithEmailAndPassword(values.email, values.password)
.then((res) => {
console.log('done!')
})
.catch(function (error) {
// Handle Errors here.
console.log(error)
})
.finally(() => {
console.log(loading)
//here loading == false too, even though I expected it to be true
setSubmitting(false)
setLoading(false)
})
}
}
>
<Form>
<FormikText label="Email:"
name="email"
type="email"
id="email" />
<FormikPassword label="Password:"
name="password"
id="password"
/>
<FormikPassword label="Confirm Password:"
name="passwordConfirm"
id="passwordCOnfirm"
/>
<FormikCheckbox
name="acceptedTerms"
id="acceptedTerms"
>
<span className={styles.checkboxLabel}>
I agree to the <Link href="/terms" ><a className={styles.registerLink}>Terms of Service</a></Link> and <Link href="/privacy"><a className={styles.registerLink}>Privacy/Cookie Policy</a></Link>
</span>
</FormikCheckbox>
<div className={styles.buttonContainer}>
<Button type="submit" color="blue" showSpinner={loading}>Sign Up</Button>
</div>
</Form>
</Formik>
</div>
</div>
</Layout>
</>
)
}
即使我Button
的以某种方式按预期工作(微调器按预期显示),在通过 函数调用console.loging
的值之后,我注意到这是 我所期望的。是因为 React 批处理调用的方式吗?我的问题是:loading
onSubmit
false
useState
- 如何以正确的方式处理这种情况?
- 如果
loading == false
在那些中console.logs
,为什么我的Button
工作按预期工作?
解决方案
是因为 React 批处理 useState 调用的方式吗?
我认为是的,这正是Formik
提供isSubmitting
标志的原因,尝试使用它而不是跟踪您自己的loading
状态,我知道它适用于您当前的规范,但是当这个组件变得更复杂时,您可能会遇到一些问题
你的代码看起来像这样
export default function register() {
return (
<>
<Layout>
<div className={styles.registerContainer}>
<div className={styles.registerFormContainer}>
<h1 className={styles.registerHeader}>Sign Up</h1>
<Formik
initialValues={{
email: "",
password: "",
passwordConfirm: "",
acceptedTerms: false,
}}
onSubmit={async (values) => {
try {
initFirebase();
await firebase
.auth()
.createUserWithEmailAndPassword(
values.email,
values.password
);
} catch (e) {
// Handle Errors here.
console.log(error);
}
}}
>
{({ isSubmitting }) => (
<Form>
<FormikText
label="Email:"
name="email"
type="email"
id="email"
/>
<FormikPassword
label="Password:"
name="password"
id="password"
/>
<FormikPassword
label="Confirm Password:"
name="passwordConfirm"
id="passwordCOnfirm"
/>
<FormikCheckbox name="acceptedTerms" id="acceptedTerms">
<span className={styles.checkboxLabel}>
I agree to the{" "}
<Link href="/terms">
<a className={styles.registerLink}>Terms of Service</a>
</Link>{" "}
and{" "}
<Link href="/privacy">
<a className={styles.registerLink}>
Privacy/Cookie Policy
</a>
</Link>
</span>
</FormikCheckbox>
<div className={styles.buttonContainer}>
<Button
type="submit"
color="blue"
showSpinner={isSubmitting}
>
Sign Up
</Button>
</div>
</Form>
)}
</Formik>
</div>
</div>
</Layout>
</>
);
}
推荐阅读
- python-3.x - Python - 如何通过使用来自其他函数的数据来更改函数中声明变量的值
- google-apps-script - 在 Google 表格中记录收到的 Gmail 邮件
- ajax - 我很难将地图数据从 ajax 发送到 spring 控制器
- sql - 以JSON形式返回时如何从同一查询中获取ID列表
- php - 如何使包配置将其不存在的键合并到 laravel 7.x 中的应用程序配置文件中?
- windows - 如何在 Windows 上读取 USB HID 报告描述符?
- java - 外键上的 JPQL JOIN 导致 SQLSyntaxErrorException
- c++ - 使用链表检测重复项
- java - 在 Java 中找不到行
- python - 即使数据库文件已被删除,表仍然存在