I have a div tag which is used as a card and I want to make the scrollbar only visible when scrolling. I have used states to do this but the scrollbar flickers on every scroll. Can anyone please help me fix this?
This is the state and handleScroll function:
const [isScroll, setscroll] = useState(true)
function handleScroll() {
console.log("scroll detected")
setscroll(!isScroll)
}
This is the div where I want to apply the scroll event:
<div className={`${description} ${isScroll ? des : ""}`} id={classes.des} onScroll={handleScroll}>
This is the CSS:
.des::-webkit-scrollbar {
display: none;
}
.description {
background-color: $color-card-backgroung;
padding: 12px;
flex: 1;
height: 100%;
text-align: left;
overflow-y: scroll;
& > label:last-child {
font-size: 1.125rem !important;
color: $color-primary-7 !important;
}
& > label:nth-child(2) {
margin-top: 16px;
}
}
In your implementation you will update the components state and re-render every time the scroll event fires, which happen a lot (see https://developer.mozilla.org/en-US/docs/Web/API/Document/scroll_event). As you are updating the state isScroll with negation (setscroll(!isScroll)) the scroll will be visible and then hidden every second time a scroll event is fired. Scroll events fires at a high rate meaning that this happens many many times. This could also cause some performance issues as you are re-rendering the component for every scroll event.
Two common ways to improve the performance for scroll events is to use debounce or throttle. Debounce will only fire a callback once within a specified interval even if the event is triggered multiple times within that interval. Throttle will fire a callback one time every X ms. In your case we can set scroll to true when the first event is fired and then use debounce to hide the scroll within a certain interval after the user stops scrolling. You can find a good article about debounce in react here: https://dmitripavlutin.com/react-throttle-debounce/ if you want to understand it better. You can use lodash to get an already implemented version of debounce (https://lodash.com/docs/4.17.15#debounce) or implemented on your own.
An updated implementation solve your problem could look something like this:
import debounce from 'lodash-es/debounce'
const debouncedScrollHandler = useMemo(debounce(() => {
setscroll(false)
}, 500), [])
const handleScroll = () => {
if(!isScroll) {
console.log("scroll detected")
setscroll(true)
}
debouncedScrollHandler()
}
Now we are setting the scroll to true as soon as the user starts scrolling and we don't set it to false until 500ms after the user has stopped scrolling. Might have missed something in the implementation but it should point you in the right direction.