Reputation: 1719
I tried to do something when user is scroll to the bottom, and following is what I did in react component.
Notices that it is work, but the weird issue is even if I add a debounce the doSomething function still fired twice when scroll reach the bottom.
I have to chage the delay from 500 to 3000 or more to avoid the issue happen. Why is that, and how to fix this problem?
componentDidMount() {
window.addEventListener('scroll', _.debounce(this.handleScroll.bind(this), 500));
}
componentWillUnmount() {
window.removeEventListener('scroll', _.debounce(this.handleScroll.bind(this), 500));
}
handleScroll() {
const documentElement = document.documentElement;
const isScrollToBottom = documentElement.clientHeight + documentElement.scrollTop === documentElement.scrollHeight;
if (isScrollToBottom) {
this.doSomething()
}
}
doSomething(){
// do something
}
Upvotes: 1
Views: 521
Reputation: 1719
If you are a mac user, the trackpad or magic mouse may cause bounce when you do a quick srolling.
Sometimes the bounce will continue for a long time (it could be two seconds or more), it depends on how quick you slick your trackpad.
So if you tried to use setTimeout to async debounce this issue, it will cost a lot of delay time.
I haven't execly fix the issue yet. But if your doSomething() is an async function, at lease you can call the function in the right order.
My way to 'temporarily' slove this problem is very similar to the Bhojendra Rauniyar's answer.
state = {
isScrolled: false
}
doSomething(){
// set isScrolled = false, when async function is done
}
if (isScrollToBottom && !isScrolled) {
this.setDelay(doSomething, 500)
}
setDelay(callback, time) {
this.setState({ isScrolled: true });
setTimeout(
() => {
callback();
},
time,
);
}
Upvotes: 0
Reputation: 85545
I was resolving exactly similar problem while I saw this question. Here's how I did it:
Set the initial state to flag if doSomething is called:
state = {
isScrolled: false
}
Call doSomething only if it is not scrolled:
if (!isScrolled) {
this.doSomething()
// set scrolled to true
this.setState({isScrolled: true})
}
In your case, you can combine the condition:
if (isScrollToBottom && !isScrolled) {
To be frankly, I tried several things to resolve this. But I resolved it after an hour, and your post was still in my window tab. Hope, you like this approach as well. This way, you even do not need to use debounce method.
BTW, I was using hooks:
const [isScrolled, setIsScrolled] = useState(false)
useEffect(() => {
doSomething()
setIsScrolled(true)
},[isScrolled])
Upvotes: 1
Reputation: 803
Try defining your debouce function a separate handler
handler = _.debounce(() => {
console.log('foo');
}, 100
then use this handler is your addEventlistener and removeEventListener
Upvotes: 0