在渲染道具中调用的 setState 导致反应警告

dag*_*da1 7 reactjs

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

这是组件:

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>
    </>
  );
};
Run Code Online (Sandbox Code Playgroud)

如果存在验证错误,则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

Run Code Online (Sandbox Code Playgroud)

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

我能做什么?

Ali*_*deh 5

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

        setTimeout(() => setHasValidationError(true), 0);
Run Code Online (Sandbox Code Playgroud)

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

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