【发布时间】:2022-01-11 09:02:42
【问题描述】:
我开始在 react 中实现一个轮播,此外,我想给它一个无限滚动的效果,也就是说,如果你一直向右点击并到达终点。从头开始。
有趣的是,我不得不使用 useState 并且我注意到非常奇怪的行为。它永远不会到达最后一个 div,而是立即转到第一个(无滚动效果)并滚动到第二个。
这是滚动发生的主文件。
Carousel.tsx
import React, { FC, useEffect, useLayoutEffect, useRef, useState } from "react";
import { useStyles, useStylesClasses } from "./CarouselCSS";
import ArrowRightAltIcon from '@mui/icons-material/ArrowRightAlt';
interface Props {
className?: string;
}
type Scroll = "left" | "right";
type Index = {
sign: "To" | "By";
value: number;
}
export const Carousel: FC<Props> = ({className, children}) => {
const {Root, Carousel} = useStyles();
const classes = useStylesClasses();
const ref = useRef(null);
const firstRun = useRef(true);
const [activeIndex, setActiveIndex] = useState<Index>({
sign: "To",
value: 0
});
// Triggers before rendering the page
// useLayoutEffect(()=>{
// console.log(ref.current.children.length);
// }, [ref])
useEffect(() => {
if(!firstRun.current)
if (activeIndex.sign === "To"){
console.log({"To": activeIndex.value})
ref.current.scrollTo({
left: (activeIndex.value*ref.current.clientWidth),
behavior: "smooth",
})
}
else{
console.log("By")
ref.current.scrollBy({
left: ref.current.clientWidth,
behavior: "smooth",
})
}
else
firstRun.current = false;
}, [activeIndex])
// controlling scrolling and making it infinite
const scroll = (value: Scroll) => {
switch(value){
case "left": {
console.log("Left")
if(activeIndex.value === 0){
setActiveIndex({sign: "By", value: ref.current.children.length - 1});
}
else{
setActiveIndex({sign: "To", value: activeIndex.value - 1});
}
}
break;
case "right": {
console.log("Right")
if(activeIndex.value === ref.current.children.length - 1){
setActiveIndex({sign: "To", value: 0});
}
else{
setActiveIndex({sign: "By", value: activeIndex.value + 1});
}
}
break;
}
}
return (
<Root>
<div onClick={() => {
scroll("left");
}
}
>
<ArrowRightAltIcon style={{transform: 'rotate(180deg)'}} className={classes.arrow}/>
</div>
<Carousel className={className} ref={ref}>
{children}
</Carousel>
<div onClick={() => {
scroll("right");
}}
>
<ArrowRightAltIcon className={classes.arrow}/>
</div>
</Root>
)
}
如果这不合理,我还将代码沙箱链接附加到整个内容。
更新
正如所建议的,组件重新渲染,因此为什么第一个 div 会立即出现。现在,我想在这里理解的是,为什么它在某些情况下会重新渲染并在某些情况下滚动?既然我用的是useState,不应该每次都重新渲染吗?
https://codesandbox.io/embed/keen-wright-9n94s?fontsize=14&hidenavigation=1&theme=dark
感谢任何帮助!
【问题讨论】:
标签: javascript reactjs