-
-
Notifications
You must be signed in to change notification settings - Fork 5.2k
/
useRestoreScrollPosition.ts
71 lines (64 loc) · 2.06 KB
/
useRestoreScrollPosition.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
import { useEffect } from 'react';
import { useStore } from '../store';
import { debounce } from 'lodash';
import { useLocation } from 'react-router';
/**
* A hook that tracks the scroll position and restores it when the component mounts.
* @param storeKey The key under which to store the scroll position in the store
* @param debounceMs The debounce time in milliseconds
*
* @example
* import { ListBase, useRestoreScrollPosition } from 'ra-core';
*
* const MyCustomList = (props) => {
* useRestoreScrollPosition('my-list');
* return <ListBase {...props} />;
* };
*/
export const useRestoreScrollPosition = (
storeKey: string,
debounceMs = 250
) => {
const [position, setPosition] = useTrackScrollPosition(
storeKey,
debounceMs
);
const location = useLocation();
useEffect(() => {
if (position != null && location.state?._scrollToTop !== true) {
setPosition(undefined);
window.scrollTo(0, position);
}
// We only want to run this effect on mount
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
};
/**
* A hook that tracks the scroll position and stores it.
* @param storeKey The key under which to store the scroll position in the store
* @param debounceMs The debounce time in milliseconds
*
* @example
* import { ListBase, useTrackScrollPosition } from 'ra-core';
*
* const MyCustomList = (props) => {
* useTrackScrollPosition('my-list');
* return <ListBase {...props} />;
* };
*/
export const useTrackScrollPosition = (storeKey: string, debounceMs = 250) => {
const [position, setPosition] = useStore(storeKey);
useEffect(() => {
if (typeof window === 'undefined') {
return;
}
const handleScroll = debounce(() => {
setPosition(window.scrollY);
}, debounceMs);
window.addEventListener('scroll', handleScroll);
return () => {
window.removeEventListener('scroll', handleScroll);
};
}, [debounceMs, setPosition]);
return [position, setPosition];
};