'How to make a useRef component?
Hi I have the following horizontal stack with images. I used two buttons on either end to scroll through the stack.
const PostDetails = props => {
let scrl = useRef(null);
const [scrollX, setscrollX] = useState(0);
const [scrolEnd, setscrolEnd] = useState(false);
//Slide click
const slide = (shift) => {
scrl.current.scrollLeft += shift;
setscrollX(scrollX + shift);
if (
Math.floor(scrl.current.scrollWidth - scrl.current.scrollLeft) <=
scrl.current.offsetWidth
) {
setscrolEnd(true);
} else {
setscrolEnd(false);
}
};
const scrollCheck = () => {
setscrollX(scrl.current.scrollLeft);
if (
Math.floor(scrl.current.scrollWidth - scrl.current.scrollLeft) <=
scrl.current.offsetWidth
) {
setscrolEnd(true);
} else {
setscrolEnd(false);
}
};
return(
<Box>
<Box style={{paddingLeft:'10%', paddingTop:'80px'} }>
<Flex justifyContent='center' alignItems='center'>
<Heading as='h4' size='md'>Top sales of all time</Heading>
</Flex>
<Box display='flex'>
{
scrollX !== 0 && (
<Button className="prev" onClick={() => slide(-300)} style={{left: '0%', top: '50%', transform: 'translate(-30%, 500%)', }}>
<ArrowBackIcon/>
<i className="fa fa-angle-left"></i>
</Button>
)}
<Stack className='stackBar' ref={scrl} onScroll={scrollCheck} overflowX='scroll' scroll-behavior='smooth' direction={['column', 'row']} spacing='24px'>
{topSalesList.obj_fulfilled_ask.map(i => {
const image = "https://ipfs.io/" + i.token.display_uri.replace(':', '');
return (
<Row tokenData = {i}/>
)
})
}
</Stack>
{!scrolEnd && (
<Button className="next" onClick={() => slide(+300)} style={{left: '0%', top: '50%', transform: 'translate(10%, 500%)',}}>
<ArrowForwardIcon/>
</Button>
)}
</Box>
</Box>
</Box>
Now this works perfectly fine, However if I want to add another replica stack and add the same two buttons on either side, I have to copy the same refs and supporting functions over and over shown below
let scrlY = useRef(null);
let scrl = useRef(null);
const [scrollX, setscrollX] = useState(0);
const [scrolEnd, setscrolEnd] = useState(false);
//Slide click
const slide = (shift) => {
scrl.current.scrollLeft += shift;
setscrollX(scrollX + shift);
if (
Math.floor(scrl.current.scrollWidth - scrl.current.scrollLeft) <=
scrl.current.offsetWidth
) {
setscrolEnd(true);
} else {
setscrolEnd(false);
}
};
const scrollCheck = () => {
setscrollX(scrl.current.scrollLeft);
if (
Math.floor(scrl.current.scrollWidth - scrl.current.scrollLeft) <=
scrl.current.offsetWidth
) {
setscrolEnd(true);
} else {
setscrolEnd(false);
}
};
const [scrollY, setscrollY] = useState(0);
const [scrolEndY, setscrolEndY] = useState(false);
//Slide click
const slideY = (shift) => {
scrlY.current.scrollLeft += shift;
setscrollY(scrollY + shift);
if (
Math.floor(scrlY.current.scrollWidth - scrlY.current.scrollLeft) <=
scrlY.current.offsetWidth
) {
setscrolEndY(true);
} else {
setscrolEndY(false);
}
};
const scrollCheckY = () => {
setscrollY(scrlY.current.scrollLeft);
if (
Math.floor(scrlY.current.scrollWidth - scrlY.current.scrollLeft) <=
scrlY.current.offsetWidth
) {
setscrolEndY(true);
} else {
setscrolEndY(false);
}
};
How can I make a ref component and just call it everytime?
Edit for clarity this is what I mean when I say adding another stack.
<Box>
<Box style={{paddingLeft:'10%', paddingTop:'80px'} }>
<Flex justifyContent='center' alignItems='center'>
<Heading as='h4' size='md'>Top sales of all time</Heading>
</Flex>
<Box display='flex'>
{
scrollX !== 0 && (
<Button className="prev" onClick={() => slide(-300)} style={{left: '0%', top: '50%', transform: 'translate(-30%, 500%)', }}>
<ArrowBackIcon/>
<i className="fa fa-angle-left"></i>
</Button>
)}
<Stack className='stackBar' ref={scrl} onScroll={scrollCheck} overflowX='scroll' scroll-behavior='smooth' direction={['column', 'row']} spacing='24px'>
{topSalesList.obj_fulfilled_ask.map(i => {
const image = "https://ipfs.io/" + i.token.display_uri.replace(':', '');
return (
<Row tokenData = {i}/>
)
})
}
</Stack>
{!scrollEnd && (
<Button className="next" onClick={() => slide(+300)} style={{left: '0%', top: '50%', transform: 'translate(10%, 500%)',}}>
<ArrowForwardIcon/>
</Button>
)}
</Box>
</Box>
</Box>
<Box style={{paddingLeft:'10%', paddingTop:'20px'} }>
<Flex justifyContent='center' alignItems='center'>
<Heading as='h4' size='md'>Recent Sales</Heading>
</Flex>
<Box display='flex'>
{
scrollX !== 0 && (
<Button className="prev" onClick={() => slide(-300)} style={{left: '0%', top: '50%', transform: 'translate(-30%, 500%)', }}>
<ArrowBackIcon/>
<i className="fa fa-angle-left"></i>
</Button>
)}
<Stack className='stackBar' ref={scrl} onScroll={scrollCheck} overflowX='scroll' scroll-behavior='smooth' direction={['column', 'row']} spacing='24px'>
{latestSalesList.obj_fulfilled_ask.map(i => {
const image = "https://ipfs.io/" + i.token.display_uri.replace(':', '');
return (
<Row tokenData = {i}/>
)
})
}
</Stack>
{!scrollEnd && (
<Button className="next" onClick={() => slide(+300)} style={{left: '0%', top: '50%', transform: 'translate(10%, 500%)',}}>
<ArrowForwardIcon/>
</Button>
)}
</Box>
</Box>
Solution 1:[1]
const useScroll = (scrl) => {
const [scrollX, setscrollX] = useState(0);
const [scrolEnd, setscrolEnd] = useState(false);
//Slide click
const slide = (shift) => {
scrl.current.scrollLeft += shift;
setscrollX(scrollX + shift);
if (
Math.floor(scrl.current.scrollWidth - scrl.current.scrollLeft) <=
scrl.current.offsetWidth
) {
setscrolEnd(true);
} else {
setscrolEnd(false);
}
};
const scrollCheck = () => {
setscrollX(scrl.current.scrollLeft);
if (
Math.floor(scrl.current.scrollWidth - scrl.current.scrollLeft) <=
scrl.current.offsetWidth
) {
setscrolEnd(true);
} else {
setscrolEnd(false);
}
};
return {scrollX,scrollEnd, slide, scrollCheck}
}
export default useScroll;
Now to use this hook you can do this.
const PostDetails = props => {
let scrl = useRef(null);
const {scrollX, scrollEnd, slide, scrollCheck} = useScroll(scrl)
return(
<Box>
<Box style={{paddingLeft:'10%', paddingTop:'80px'} }>
<Flex justifyContent='center' alignItems='center'>
<Heading as='h4' size='md'>Top sales of all time</Heading>
</Flex>
<Box display='flex'>
{
scrollX !== 0 && (
<Button className="prev" onClick={() => slide(-300)} style={{left: '0%', top: '50%', transform: 'translate(-30%, 500%)', }}>
<ArrowBackIcon/>
<i className="fa fa-angle-left"></i>
</Button>
)}
<Stack className='stackBar' ref={scrl} onScroll={scrollCheck} overflowX='scroll' scroll-behavior='smooth' direction={['column', 'row']} spacing='24px'>
{topSalesList.obj_fulfilled_ask.map(i => {
const image = "https://ipfs.io/" + i.token.display_uri.replace(':', '');
return (
<Row tokenData = {i}/>
)
})
}
</Stack>
{!scrolEnd && (
<Button className="next" onClick={() => slide(+300)} style={{left: '0%', top: '50%', transform: 'translate(10%, 500%)',}}>
<ArrowForwardIcon/>
</Button>
)}
</Box>
</Box>
</Box>)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Shivam Mishra |
