我有一个useEffect,它在每次用户在输入中键入内容时触发。起初,我让它以useState运行,运行起来像黄油一样流畅,但我被要求将其更改为useReducer。UseReducer的useEffect:
useEffect(() => {
dispatch({type : 'username', payload : watch().username});
dispatch({type : 'password', payload : watch().password});
console.log(state.username, state.password);
}, [watch()]);
UseEffect with useState:
useEffect(() => {
setPassword(watch().password);
setUsername(watch().username);
console.log(username, password);
}, [watch()]);
而且,即使用户没有输入任何内容,useEffect也会不断地被触发,因为当与useState一起使用时,它不会这样做。
减速机:
const reducer = (state, action) => {
switch (action.type) {
case "username":
return {...state, username: action.payload };
case "password":
return {...state, password : action.payload};
}
};
1条答案
按热度按时间kpbpu0081#
这里有一些危险信号,但最突出的是您如何使用
watch()
。useEffect
和useState
(可能)将在每次渲染时重新运行,因为watch()
可能正在返回非备注对象。您的代码使用useState
“工作”的原因是setting a state object to the same thing does nothing--如果用户名或密码没有更改,则状态不会更新,因此组件不会重新呈现。但
useReducer
并非如此,除非您在Reducer函数中显式地满足它--下面这样的代码可能会修复这个错误:但是,您还应该尝试使挂钩的依赖项尽可能简单。有什么原因不能先调用
watch()
,然后将值传递给您的效果吗?或者,您可以更好地将两者分为两种不同的效果-如果
password
已更改,则无需发送username
更新:而且,当我们处于重构模式时,为什么不创建一个定制钩子来为您处理逻辑呢?类似于: