I am trying to make an infinite horizontal scroll feature, where when the user reaches the rightmost or the last item of the list, an API request will be triggered and the user can scroll more.
I am already able to somewhat achieve this using the onTouchEnd event handler. However, upon getting the next items, it adds it and then scrolls back to the first item. I guess that has something to do with re-rendering in react?
Is there perhaps some better way of handling this? Or at the very least, go back to the previous position the user scrolled to. I've searched a lot of libraries but they don't seem to achieve what I need.
Here is what I have done so far:
import React from 'react';
import { Box, Avatar } from '@mui/material';
import {
useDispatch,
useSelector,
} from '../../../../redux/store/configureStore';
import {
nextPage,
fetchAsyncMerchants,
} from '../../redux/slices/deals/Merchants';
const MerchantList = () => {
const dispatch = useDispatch();
const limit = 10;
const { skip, merchants } = useSelector((state) => state.merchants);
const boxWidthRef = React.useRef();
React.useEffect(() => {
dispatch(fetchAsyncMerchants({ skip, limit }));
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [skip]);
return (
<Box sx={{ mt: '12px', mb: '16px' }}>
{merchants && (
<Box
ref={boxWidthRef}
onTouchEnd={(event) => {
dispatch(nextPage(limit)); //updates the skip counter to rerun useEffect
}}
onTouchStart={(event) => {
console.log(event.touches[0]);
}}
sx={{
minHeight: '120px',
boxShadow: 5,
display: 'flex',
justifyContent: 'space-between',
borderRadius: '16px',
overflow: 'auto',
p: '0 5px',
}}
>
{merchants.map((merchant) => {
return (
<Box
id="card-btn"
key={merchant.id}
sx={{
display: 'flex',
flexDirection: 'column',
minWidth: '100px',
}}
>
<Avatar
sx={{
height: '40px',
width: '40px',
mb: '4px',
}}
src={merchant.logo}
/>
</Box>
);
})}
</Box>
)}
</Box>
);
};
export default MerchantList;