【问题标题】:useEffect React Hook rendering multiple times with async await (submit button)useEffect React Hook 使用异步等待多次渲染(提交按钮)
【发布时间】:2020-01-17 19:16:15
【问题描述】:

我试图基本上禁用提交按钮,这样我的 api 调用只会触发一次/在操作正在进行时有人不能再次点击提交。

我将 runOnSubmit 函数转换为异步函数并直接调用它。我已经基于许多其他解决方案,基本上当我这样做和调试时,我可以说 isSubmitting 仍然设置为 true 并且钩子被多次调用/ submitAsync 函数被调用两次。

基本上,setSubmitting 会被调用,但实际上在再次刷新之前不会执行任何操作。我希望它只被调用一次。我不知道为什么 submitAsync 甚至会运行多次,因为依赖项(错误)没有改变。如果它们发生变化,那么 noErrors 第二次会有所不同,甚至不会命中该块。

useEffect(() => {

        if (isSubmitting) {
            const noErrors = Object.keys(errors).length === 0;
            if (noErrors) {

                const submitAsync = async () => {
                    await runOnSubmit()
                    setSubmitting(false)
                }

                // clear out touched upon submission
                setTouched([]);
                submitAsync();
            } else {
                setSubmitting(false);
            }
        }
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [errors]);

更新-添加更多信息:

 // function for form submission
    const handleSubmit = (event) => {
        event.preventDefault();
        const validationErrors = validate(values);
        setErrors(validationErrors);
        setSubmitting(true);
    }

由于这个函数将 Submitting 设置为 true,它应该重新运行 useEffect 函数,因为 isSubmitting 在依赖数组中。

按钮调用提交并禁用它:

<Button 
 disabled={isSubmitting} 
 buttonType="submit" 
 text="Create Account" />

我的按钮组件:

<button 
  type={props.buttonType}
  disabled={props.disabled}
  onClick={props.onClick}>
     {props.text}
 </button>

第二次编辑-在 console.logs 中添加:

useEffect(() => {
        console.log("use effect running", isSubmitting)
        if (isSubmitting) {
            console.log("use effect submitting true")
            const noErrors = Object.keys(errors).length === 0;
            if (noErrors) {
                console.log("use effect no errors")
                const submitAsync = async () => {
                    console.log("inside submit async")
                    await runOnSubmit()
                    console.log("after function")
                    setSubmitting(false)
                    console.log("after set false")
                }

                // clear out touched upon submission
                setTouched([]);
                submitAsync();
                console.log("console after submit")
            } else {
                setSubmitting(false);
            }
        }
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [isSubmitting === true]);

运行时:

use effect running true
use effect submitting true
use effect no errors
inside submit async
the user called signup method
console after submit
after function
after set false
use effect running false

这里没有多大意义的问题是“提交后的控制台”在“函数后”之前运行。就好像异步等待没有做任何事情。

【问题讨论】:

  • 似乎提供的代码不足以重现您的问题。 [errors] 作为useEffect 钩子的第二个参数可能会导致它过时并且在errors 对象更改之前不会重新运行。但这取决于您如何声明和修改errors。或者useEffect 可能在每次渲染后被调用,这主要取决于isSubmitting 是如何改变的
  • 我实际上认为你是对的,不知道为什么我什至在那里使用错误。我将依赖数组更改为[isSubmitting === true],因为我希望它仅在提交时重新运行。问题是我可以连续点击提交并且它没有被禁用。在上面添加handleSubmit函数和提交按钮
  • 我将您的代码放在代码沙箱中,无法重现您的问题。 codesandbox.io/s/useeffect-called-twice-0ybcy
  • 这太奇怪了。我会尝试放置完整的代码,但它使用了我们所有的后端 api,所以很难复制。我在 console.logs 中添加了,很明显它没有等待响应。也许我需要尝试使用 Promise,但我已经尝试过 .then().catch() 等差异
  • @StephenPhillips 如果我们看不到errors 的来源以及它是如何声明和修改的,那么将很难帮助解决您的问题。也不清楚为什么 isSubmitting 不在您的依赖数组中,因为您在回调正文中引用了它。

标签: javascript reactjs async-await use-effect


【解决方案1】:

致遇到此问题的任何新人:

传递给useEffect 的第二个数组参数可能会导致多次渲染。只传入一个数组[],它会渲染一次。

如上所述here 通过反应官方网站。如果在重新渲染之间没有发生某些更改,则可以停止效果。这将防止它多次渲染

【讨论】:

    猜你喜欢
    • 2019-02-10
    • 2021-05-16
    • 1970-01-01
    • 1970-01-01
    • 2022-11-26
    • 2021-11-21
    • 1970-01-01
    • 2023-03-18
    • 2020-12-01
    相关资源
    最近更新 更多