React useCallback 钩子:这些 handleChange 和 handleSubmit 函数的正确依赖项是什么,以防止重新渲染?

React useCallback hook: What are the correct dependencies for these handleChange & handleSubmit functions to prevent re rendering?

我有一个登录组件,它会不必要地重新呈现。我用 React.memo and am using the useCallBack 钩子包装了组件,以防止在值不改变的情况下在每次渲染时创建这些函数...

考虑以下因素:

我有一个通用的 FormComponent,它得到一个道具:

function FormComponent({
   formType
}) { ....}

export default React.memo(FormComponent)

该道具将在我拥有的不同形式之间切换,例如登录、注册等 在我的例子中,我只是展示了登录表单,我想我会把解决方案应用到其他人身上。

function FormComponent({
  formType
}) {

/* various setstate removed for brevity */

  const Forms = {
    Login: [LoginForm,
      () => loginSubmit(
        email,
        password,
        setEmail,
        setPassword,
        setFormError,
        setFormSuccess,
        setIsLoading,
        setResponseMessage,
        dispatch,
        router,
        user,
        mutate
      )
    ]
  };

  function handleChangeForUseCallBack(name, value) {
    setResponseMessage('');
    setPasswordFeedback('')
    setPasswordConfirmationFeedback('')
    setFormError(false);
    setFormSuccess(false);
    setEmailError(false);
    setPasswordError(false);
    setPasswordConfirmationError(false);
    setDisableButton(false);

    dispatch({ type: 'resetUserAccountIsVerified', })

    setEmailDup(false);


    if (value === '') setDisableButton(() => true)

    if (name === 'email') {
      setEmail(value);
    }

    if (name === 'password') {
      setPassword(value);
    }

    if (name === 'password_confirmation') {
      setPasswordConfirmation(value);
    }

    if (name === 'current_location') {
      setCurrentLocation(value);
    }

    if (name === 'current_destination') {
      setCurrentDestination(value);
    }

    if (name === 'interested_activities') {
      setInterestedActivitiesInput(value);
    }
  }

  const handleChange = useCallback((e) => {
    e.persist();
    const { name, value } = e.target;
    handleChangeForUseCallBack(name, value);
  }, [email, formType, password, password_confirmation, handleChangeForUseCallBack, setIsLoading]);

  function handleSubmitForUseCallBack(e, form) {
    e.preventDefault();
    setDisableButton(true);
    validateInputs(
      form,
      email,
      setEmailError,
      setEmailFeedback,
      password,
      password_confirmation,
      setPasswordConfirmationError,
      setPasswordConfirmationFeedback,
      setPasswordError,
      setPasswordFeedback,
      setFormSuccess,
      setFormError,
    );
    return preventSubmit ? false : Forms[form][1]()
  }

  const handleSubmit = useCallback((e, form) => {
    handleSubmitForUseCallBack(e, form);
  }, [email, password, password_confirmation, interestedActivities, handleSubmitForUseCallBack]);

  function LoginForm() {
    useEffect(() => {
      dispatch({ type: 'resetUserAccountIsVerified' })
    }, [id]);

    return (
      mounted && <GenericFormComponent
        handleSubmit={handleSubmit}
        formType={formType}
        formSuccess={formSuccess}
        formError={formError}
        accountNotVerified={accountNotVerified}
        email={email}
        emailError={emailError}
        emailFeedback={emailFeedback}
        handleChange={handleChange}
        password={password}
        passwordError={passwordError}
        passwordFeedback={passwordFeedback}
        disableButton={disableButton}
        buttonName="Log-in"
        isLoading={isLoading}
        setIsLoading={setIsLoading}
        responseMessage={responseMessage}
      />
    );
  }

  return Forms[formType][0]();
}

问题是 handleSubmit 有各种函数调用和传递的值需要传递到 useCallback 依赖项中吗?

如有任何帮助,我们将不胜感激!

我认为 useCallback 不是这里的问题。一个潜在的原因可能是在呈现 LoginForm 时出现以下副作用 运行:

useEffect(() => {
  dispatch({ type: 'resetUserAccountIsVerified' })
}, [id]);

但我可能错了。我认为这里的明确问题是 LoginForm 是在 FormComponent 中定义的。由于它在 FormComponent 内部定义,每次 FormComponent 被重新评估(例如,从状态更改), LoginForm 将被重新初始化,因此如果它已经呈现,那么它将重新呈现。我认为在别处定义 LoginForm 可以解决您的问题。