首页 > 解决方案 > 在渲染道具中调用的 setState 导致反应警告

问题描述

我有以下组件,它采用渲染道具,它将值传递给子组件。 是一个显示问题的代码框。按提交并查看控制台。

这是组件:

export const FormContainer = function FormContainer<V>({
  initialValues,
  validate,
  render,
  ...rest
}: FormContainerProps<V>) {
  const [hasValidationError, setHasValidationError] = useState(false);
  const dispatch = useDispatch();

  useEffect(() => {
    if (!hasValidationError) {
      return;
    }

    scrollToValidationError();

    () => setHasValidationError(false);
  }, [hasValidationError]);

  return (
    <>
      <Formik
      >
        {({
          isSubmitting,
          submitCount,
          isValid,
          errors,
          values,
        }: FormikProps<V>) => {
          const invalid = !isValid;
          const submitted = submitCount > 0;

          if (submitCount > 0 && invalid) {
            setHasValidationError(true);
          }

          return (
            <>
              <Form>
                  <div className={styles.form}>
                    {render({
                      values,
                      errors,
                      isSubmitting,
                      invalid,
                      submitCount,
                    })}
                  </div>
              </Form>
            </>
          );
        }}
      </Formik>
    </>
  );
};

如果存在验证错误,则setHasValidationError调用它会导致此错误从反应

Warning: Cannot update a component (`FormContainer`) while rendering a different component (`Formik`). To locate the bad setState() call inside `Formik`, follow the stack trace as described in 
    in Formik (created by FormContainer)
    in FormContainer (created by Home)
    in Home (created by Context.Consumer)
    in Route (created by App)
    in Switch (created by App)
    in Router (created by App)
    in App

我并不是说这个警告是错误的。在这里调用setHasValidationError似乎并不理想,但scrollToValidationError();在初始useEffect挂钩中调用的调用是异步的,它需要在渲染函数之外进行。

我能做些什么?

标签: reactjs

解决方案


为了避免 Formik 出现这个问题,您可以将状态调用包装在 setTimeouts 中,这应该可以解决问题:

        setTimeout(() => setHasValidationError(true), 0);

这也是 Formik 在其官方文档中所做的。这是他们有一段时间的问题,诀窍是让状态更新在下一个周期滴答声中运行。

另见:https ://github.com/jaredpalmer/formik/issues/1218


推荐阅读