admin管理员组文章数量:1180476
I'm trying to override Ctrl+scroll behavior on a component, but it's not working with the error [Intervention] Unable to preventDefault inside passive event listener due to target being treated as passive. See <URL>
. I think I'm okay with using an active listener, so is there a way to specify that through React? Note that I need to access and modify state within onWheel
.
const onWheel = (e: React.WheelEvent): void => {
if (e.altKey) {
e.preventDefault();
// Error
} else if (e.ctrlKey) {
e.preventDefault();
// Error
}
};
...
return (<div className={styles["workspace"]} onWheel={onWheel}>
stuff
</div>);
I'm trying to override Ctrl+scroll behavior on a component, but it's not working with the error [Intervention] Unable to preventDefault inside passive event listener due to target being treated as passive. See <URL>
. I think I'm okay with using an active listener, so is there a way to specify that through React? Note that I need to access and modify state within onWheel
.
const onWheel = (e: React.WheelEvent): void => {
if (e.altKey) {
e.preventDefault();
// Error
} else if (e.ctrlKey) {
e.preventDefault();
// Error
}
};
...
return (<div className={styles["workspace"]} onWheel={onWheel}>
stuff
</div>);
Share
Improve this question
edited Jun 11, 2024 at 15:40
greim
9,4276 gold badges35 silver badges35 bronze badges
asked Aug 30, 2020 at 23:22
Jeff DemancheJeff Demanche
7641 gold badge7 silver badges25 bronze badges
2 Answers
Reset to default 29A bit late, but maybe it helps someone else.
The problem is that React uses passive event handlers by default with wheel, touchstart and touchmove events - in other words, you can't call stopPropagation
within them.
If you want to use non-passive event handlers, you need to use refs and add/remove event handler manually, like this:
class MyComponent extends React.Component {
myRef = React.createRef();
componentDidMount() {
// IMPORTANT: notice the `passive: false` option
this.myRef.current.addEventListener('wheel', this.handleWheel, { passive: false });
}
componentWillUnmount() {
this.myRef.current.removeEventListener('wheel', this.handleWheel, { passive: false });
}
handleWheel = (e) => {
e.stopPropagation();
// ...
}
// ...
}
Should be similar with hooks.
For anyone using functional components, here is a solution, taking inspiration from @johndodo
If your onWheel
does not change over time
function MyComponent {
const onWheel = useCallback(
(e) => {
console.log(e);
e.preventDefault();
},
[],
);
const divRefCallback = useCallback(
(node) => {
console.log(node);
if (node == null) {
return;
}
node.addEventListener('wheel', onWheel, { passive: false });
},
[onWheel],
);
return <div ref={divRefCallback}>...</div>;
}
The reason to use a useCallback
for divRef
instead of useRef
+ useEffect
is this.
If your onWheel
changes over time
e.g. if it depends on a state.
This requires some extra work because you need to remove the old event listener.
function MyComponent {
const [x, setX] = useState(0);
const onWheel = useCallback(
(e) => {
console.log(e);
console.log(x);
e.preventDefault();
},
[x],
);
const divRef = useRef(null);
const divRefCallback = useCallback(
(node) => {
console.log(node);
if (node == null) {
if (divRef.current != null) {
/* This happens when the <div> component tries to detach the old divRefCallback.
* Since we are inside a `useCallback`, the `onWheel` callback being remove is still the old one here.
*/
divRef.current.removeEventListener('wheel', onWheel, { passive: false });
}
return;
}
divRef.current = node;
node.addEventListener('wheel', onWheel, { passive: false });
},
[onWheel],
);
return <div ref={divRefCallback}>...</div>;
}
版权声明:本文标题:javascript - React onWheel handler can't preventDefault because it's a passive event listener - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1738196146a2068172.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论