首页  >  问答  >  正文

从表单提交处理程序内部调用自定义钩子 setState 不会更新状态

表单中的字段要求我关注它们才能显示错误消息。我希望在我尚未聚焦字段时单击“提交”时出现错误消息。

这是钩子(怀疑是关于稍后的 setIsTouched 调用):

const useInputModifed = (validationArray) => {
  const [enteredValue, setEnteredValue] = useState("");
  const [isTouched, setIsTouched] = useState(false);

  //   [{errorName:,fn:validationFn}]
  let errorArray = [];

  for (const errorEntry of validationArray) {
    if (errorEntry.isErrorFn(enteredValue)) {
      errorArray.push(errorEntry.errorName);
    }
  }

  const hasError = errorArray.length > 0 && isTouched;

  const valueChangeHandler = (event) => {
    setEnteredValue(event.target.value);
  };

  const reset = () => {
    setEnteredValue("");
    setIsTouched(false);
  };

  console.log(errorArray, isTouched);

  return {
    value: enteredValue,
    validationArray: errorArray,
    hasError,
    valueChangeHandler,
    setIsTouched,
    isTouched,
    reset,
  };
};

这是表单处理程序(我为每个字段使用了别名):

const formSubmissionHandler = (event) => {
    event.preventDefault();
    touchNameField(true);
    touchEmailField(true);


    if (nameInputHasError || emailInputHasError) {
 //console logging both fields gives false even after touching
      return;
    }
  
    if (!nameInputHasError && !emailInputHasError) {
      resetNameInput();
      resetEmailInput();
    }
  };

以验证名称字段为空为例,我单击开头的提交按钮。 目前在 const hasError = errorArray.length > 0 && isTouched; 中,数组有元素,但 isTouched 为 false,因为我没有聚焦该字段。

然后是“touchNameField(true);”进来了。我尝试使 hasError 为 true,但它仍然显示为 false。

setState 调用是异步的,这是问题所在吗?如果我删除重置调用它就可以了。但我仍然不明白为什么 nameInputError 等是 false。

P粉976488015P粉976488015423 天前919

全部回复(1)我来回复

  • P粉057869348

    P粉0578693482023-09-17 10:21:46

    如果不运行它,我相信这是因为 errorArrayhasError 对更改没有反应。因此,这还取决于您实例化该钩子的位置。 如果不进行测试,我会尝试以下操作:

    const useInputModifed = (validationArray) => {
      const [enteredValue, setEnteredValue] = useState("");
      const [isTouched, setIsTouched] = useState(false);
    
      const [errorArray, setErrorArray] = useState([]);
      const [hasError, setHasError] = useState(false);
    
      useEffect(() => {
        const newErrorArray = [];
        for (const errorEntry of validationArray) {
          if (errorEntry.isErrorFn(enteredValue)) {
            newErrorArray.push(errorEntry.errorName);
          }
        }
        setErrorArray(newErrorArray);
      }, [validationArray, enteredValue])
    
      useEffect(() => {
        setHasError(errorArray.length && isTouched);
      }, [errorArray, isTouched])
    
      const valueChangeHandler = (event) => {
        setEnteredValue(event.target.value);
      };
    
      const reset = () => {
        setEnteredValue("");
        setIsTouched(false);
      };
    
      console.log(errorArray, isTouched);
    
      return {
        value: enteredValue,
        validationArray: errorArray,
        hasError,
        valueChangeHandler,
        setIsTouched,
        isTouched,
        reset,
      };
    };
    

    同样,未经测试,您可能需要一些调整。

    回复
    0
  • 取消回复