【发布时间】:2020-04-27 02:10:45
【问题描述】:
目标:
在组件挂载时订阅鼠标滚轮
event。用
newValue更新组件的state.scrollTop,其中:
newValue = Math.max(0, state.scrollTop + event.deltaY)
- 在不禁用默认规则的情况下保持 react hooks linter 愉快。
代码:
const [ state, setState ] = useState({ scrollTop: 0 });
useEffect(function subscribeToWheelEvent() {
const updateScroll = function(e) {
if(!!e.deltaY) {
const delta = Math.sign(e.deltaY) * 10.0;
const val = Math.max(0, state.scrollTop + delta);
console.log(delta, val);
setState({ scrollTop: val })
} else {
console.log('zero', e.deltaY);
}
}
window.addEventListener('mousewheel', updateScroll);
console.log('subscribed to wheelEvent')
return function () {
window.removeEventListener('mousewheel', updateScroll);
}
}, []);
预期结果:
state.scrollTop 值根据滚动方向将每个鼠标滚轮事件更新 +-10,如果 newValue 小于 0,则上限为 0。
当前结果:
state.scrollTop 值没有正确更新,在 0 和 10 之间切换,可能是因为它在 updateScroll 中被记忆并保持为 0。
linter 通知我应该包含 state.scrollTop 作为效果的依赖项,但我不希望这样,因为它应该只在组件挂载时执行一次。
跟随 linter 会导致无限循环。
或者,将updateScroll 移到订阅功能之外,然后根据 linter 的建议,将 updateScroll 添加到依赖项中,并且(再次遵循 linter)用 useCallback(updateScroll, [state.scrollTop] ) 包装 updateScroll 导致订阅/取消订阅轮子每次 scrollTop 更改时发生的事件。
替代代码:
const [ state, setState ] = useState({ scrollTop: 0 });
const updateScroll = useCallback(function(e) {
if(!!e.deltaY) {
const delta = Math.sign(e.deltaY) * 10.0;
const val = Math.max(0, state.scrollTop + delta);
console.log(delta, val );
setState({ scrollTop: val })
} else {
console.log('zero', e.deltaY);
}
}, [ state.scrollTop ])
useEffect(function subscribeToWheelEvent() {
window.addEventListener('mousewheel', updateScroll);
console.log('subscribed to wheelEvent')
return function () {
window.removeEventListener('mousewheel', updateScroll);
console.log('unsubscribed to wheelEvent')
}
}, [ updateScroll ]);
问题:
如何实现目标?
【问题讨论】:
-
存在一些边缘情况,其中 linter 没有首选选项。我认为对于你想要完成的事情,你需要使用你的第一种方法。
标签: javascript reactjs react-hooks create-react-app eslint