Reputation: 381
I added listener on scroll, and tried to use event. How can I describe type instead of any ?
React 16.8.6 Tpescript 3.4
const Component: FC<IProps> = ({ children, scrollOffset, getScrollTop, videoListScrollUpdate }) => {
const scroller = useRef<HTMLDivElement>(null)
useEffect(() => {
if (scrollOffset && scroller.current) {
scroller.current.scrollTop = scrollOffset
return
}
if (getScrollTop && scroller.current) {
scroller.current.addEventListener('scroll', (e: any) => getScrollTop(e.target.scrollTop))
}
}, [])
}
Upvotes: 27
Views: 69157
Reputation: 51
const onScroll = (event: UIEvent) => {
const target = event.target as HTMLElement;
if (target && target.scrollTop + target.clientHeight + 1 >= target.scrollHeight) {
// do the magic
}
};
Upvotes: 3
Reputation: 10522
document.addEventListener("scroll", (event) => {
const e = event as WheelEvent;
// do stuff
});
Upvotes: 6
Reputation: 1866
So, I'm just going to expand on the answer from @ManjuPrabhu
Header.tsx
const Header: React.FC<IHeader> = () => {
const [scrolling, setScrolling] = useState(false);
useEffect(() => {
window.addEventListener('scroll', onScroll);
return () => {
window.removeEventListener('scroll', onScroll);
};
});
const onScroll = (e: Event) => {
const window = e.currentTarget as Window;
let currentPosition = window.scrollY;
currentPosition > 0 ? setScrolling(true) : setScrolling(false);
};
return (
<div
// clsx is a npm package for conditional classes
className={clsx('navbar sticky top-0 z-50', {
'shadow-2xl': scrolling,
})}
>
Header content
</div>
);
};
tsconfig.json
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
...
],
Upvotes: -2
Reputation: 462
This worked for me -
//register the scroll event listener callback function
useEffect(() => {
window.addEventListener('scroll', onScroll)
return () => {
window.removeEventListener('scroll', onScroll)
}
})
// scroll event callback function
const onScroll = (e: Event) => {
const window = e.currentTarget as Window
//... rest of you function
}
Make sure to include dom lib in tsconfig.json
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
...
],
Upvotes: 4
Reputation: 1774
You can use
(e: React.UIEvent<HTMLElement>)
. Described under the UIEvent from SyntheticEvents.
That said, I would advise against using useRef
within a useEffect
. It's tricky to determine whether useEffect
was re-called and scroller.current
wasn't null (even console.log
can be misleading about it).
However I would suggest to instead use the inbuilt onScroll
prop on the component you are attaching the ref
to, and give it a callback to handle the scroll. That way you don't need to attach it manually in the useEffect hook where you are forgetting to remove it on unmount(memory leak problems).
interface IProps {
children: React.ReactNode;
getScrollTop: (scrollTop: number) => whatever;
// Your other Props
}
const ScrollComponent: React.FC<IProps> = ({
children,
getScrollTop,
// Your other props
}): JSX.Element => {
const handleScroll = (e: React.UIEvent<HTMLElement>): void => {
e.stopPropagation() // Handy if you want to prevent event bubbling to scrollable parent
console.log({
event: e,
target: e.target, // Note 1* scrollTop is undefined on e.target
currentTarget: e.currentTarget,
scrollTop: e.currentTarget.scrollTop,
});
const { scrollTop } = e.currentTarget;
getScrollTop(scrollTop);
};
return (
<div
// I am assuming you were referencing your scroller as follows.
// ref={scroller}
onScroll={handleScroll} // Use the onScroll prop instead.
>
{children}
</div>
);
};
Note *1:
scrollTop wont be available on e.target.scrollTop
, much as you can see in in the console.log
, but on e.currentTarget.scrollTop
, since currentTarget calls the element on which the event handler is attached to.
Upvotes: 33