I am trying to prevent window scrolling with e.preventDefault()
when a wheel event is fired but browser scrolls no matter what.
<div onWheel={this.handleWheelEvent} >
<div className='yellow fullpage'>Yellow Page</div>
<div className='green fullpage'>Green Page</div>
<div className='blue fullpage'>Yellow Page</div>
</div>
js
handleWheelEvent = e => {
e.preventDefault();
e.stopPropagation();
e.nativeEvent.stopImmediatePropagation();
// those 3 should prevent browser from scrolling but they don't
}
Event bubbling in React refers to when the innermost component handles an event, and events bubble outwards. In React, the innermost element will first be able to handle the event, and then surrounding elements will then be able to handle it themselves.
event.stopPropagation() This will stop any parent component's event from firing. To use this: Make sure to pass the event object as a parameter. Use the stopPropagation method on the event object above your code within your event handler function.
The preventDefault() method cancels the event if it is cancelable, meaning that the default action that belongs to the event will not occur. For example, this can be useful when: Clicking on a "Submit" button, prevent it from submitting a form.
As a unified cross-browser wrapper around the browser's native events, React SyntheticEvent provides a unified API, prevents browser inconsistencies, and ensures that the event works across multiple platforms.
I couldn't find a way to prevent scrolling in React events but it's possible to achieve same effect using refs
In constructor:
this.divRef = React.createRef()
this.preventDefault = e => e.preventDefault()
In render:
<div ref={this.divRef} >
<div className='yellow fullpage'>Yellow Page</div>
<div className='green fullpage'>Green Page</div>
<div className='blue fullpage'>Yellow Page</div>
</div>
Adding and removing preventDefault event listener:
componentDidMount () {
this.divRef.current.addEventListener('wheel', this.preventDefault)
}
componentWillUnmount () {
this.divRef.current.removeEventListener('wheel', this.preventDefault)
}
React binds all events at the root element (not the document
), and the wheel
event is binded internally using true
option, and I quote MDN:
A Boolean that, if true, indicates that the function specified by listener will never call preventDefault(). If a passive listener does call preventDefault(), the user agent will do nothing other than generate a console warning
This is how I did blocked the page from scrolling while using the wheel to affect an input field:
const wheelTimeout = useRef()
const onWheel = e => {
// ... some code I needed ...
// while wheel is moving, do not release the lock
clearTimeout(wheelTimeout.current)
// flag indicating to lock page scrolling (setTimeout returns a number)
wheelTimeout.current = setTimeout(() => {
wheelTimeout.current = false
}, 300)
}
// block the body from scrolling (or any other element)
useEffect(() => {
const cancelWheel = e => wheelTimeout.current && e.preventDefault()
document.body.addEventListener('wheel', cancelWheel, {passive:false})
return () => document.body.removeEventListener('wheel', cancelWheel)
}, [])
Reference discussions:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With