我有一个不必要重新渲染的登录组件。我已经用 React.memo 包装了组件,并使用 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
可以解决你的问题。