The throttle strategy minimises the number of calls made within a certain time interval.
Unlike debouncing which calls the function when the event hasn't been carried out for a while, throttling calls the function while the event is being carried out.
const throttle = (fn, delay = 500) => {
let id;
return function (...args) {
if (id) return; // exit if timer exists
fn(...args);
id = setTimeout(() => {
id = null; // release lock
}, delay);
};
};
const InfiniteScroll = () => {
const [users, setUsers] = useState([]);
const fetchUsers = useCallback(async () => {
const res = await fetch(
"https://random-data-api.com/api/users/random_user?size=50"
);
const data = await res.json();
setUsers((users) => [...users, ...data]);
}, []);
useEffect(() => {
fetchUsers();
}, []);
const ref = useRef(null);
const hello = useCallback(
(e) => {
const portionScrolled =
e.target.scrollTop / (e.target.scrollHeight - e.target.offsetHeight);
if (portionScrolled > 0.8) {
fetchUsers();
}
},
[fetchUsers]
);
useEffect(() => {
const scrollCont = ref.current;
scrollCont.addEventListener("scroll", throttle(hello));
return () => {
scrollCont.removeEventListener("scroll", throttle(hello));
};
}, [ref, hello]);
return (
<Wrapper ref={ref}>
{users.length > 0 ? (
<UsersWrapper>
{users.map((user, index) => (
<User key={user.id}>
<UserAvatar
src={user.avatar}
letter={user.first_name[0].toUpperCase()}
/>
{user.first_name}
</User>
))}
</UsersWrapper>
) : (
<SkeletonUsers/>
)}
</Wrapper>
);
};
Note: Code snippets do not include styling details unless they are the focus of the exercise.
Copyright © 2022 Explore React