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
可以解决您的问题。
我有一个登录组件,它会不必要地重新呈现。我用 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
可以解决您的问题。