当state和redux存储应该一起工作时,我遇到了钩子重用的问题。我简化了一个代码来显示问题。
有一个组件我想使用多个钩子(为了简单起见,我在这里重用useMouseDown
钩子(:
export function Counter() {
const count = useSelector(selectCount);
const dispatch = useDispatch();
const plusSighRef = useRef<HTMLButtonElement>(null);
useMouseDown({
ref: plusSighRef,
onMouseDown: () => {
console.log('in first hook');
dispatch(increment());
}
});
useMouseDown({
ref: plusSighRef,
onMouseDown: () => { console.log('in second hook'); }
});
return <button ref={plusSighRef}>+</button>;
}
每个钩子都有内部状态,并在鼠标按下事件时有自己的回调:
const useMouseDown = ({ ref, onMouseDown }) => {
const [isClicked, setIsClicked] = useState(false);
useEffect(() => {
const element = ref.current;
const down = (e: MouseEvent) => {
setIsClicked(true);
onMouseDown(e);
}
element.addEventListener('mousedown', down);
return (): void => {
element.removeEventListener('mousedown', down);
};
}, [onMouseDown, ref]);
}
因此,第二个钩子中的mousedown事件永远不会被触发。问题是重新渲染发生在第二个钩子启动之前。
我找到了一些解决方案,但两者都不喜欢:
- 在第一个钩子鼠标向下道具中使用类似
setTimeout(() => dispatch(increment()), 0)
的东西。但就重复使用而言,这似乎并不明显 - 将两个钩子重写为一个,并使用一个"钩子"进行操作;"大";鼠标放下处理程序。但在这种情况下,一个组合的钩子可能很难维持
所以我需要一个允许保持结构原样的解决方案(我指的是两个独立的钩子(,但第二个钩子也在工作。有人能帮忙拿吗?
难道不能将逻辑保留在两个不同的函数中,并在钩子的onMouseDown
函数中顺序执行它吗?
const executeFirstFlow = () => {
console.log('in first function');
dispatch(increment());
};
const executeSecondFlow = () => {
console.log('in second function');
};
useMouseDown({
ref: plusSighRef,
onMouseDown: () => {
executeFirstFlow();
executeSecondFlow();
}
});