如何解决滑块中的 Reactjs 意外 useState 行为
我使用 useEffect 实现了自动播放滑块(有三张卡片),但手动“上一个”和“前进”按钮无法正常工作。 useState 没有根据需要更新值。 useState 正在改变我无法理解的随机行为的值。一旦我点击上一个或向前箭头来滑动幻灯片,它就会非常快速地开始更改幻灯片。自动滑块工作正常,但我手动滑动而不是 usestate 意外更改值。我如何实现自动和手动(向前和向后箭头),以便 usestate 平滑更改值。
import React,{ useState,useRef,useEffect } from "react";
import { Card,Grid } from "@material-ui/core";
import { makeStyles } from "@material-ui/core/styles";
import { SlideData,SliderImages } from "./SlideData";
import left from "../../../styles/img/homepg/AdmSlider/left.png";
import right from "../../../styles/img/homepg/AdmSlider/right.png";
function NewsSlider() {
const classes = useStyles();
const firstRef = useRef(null);
const secondRef = useRef(null);
const thirdRef = useRef(null);
const currentRef = useRef(null);
const Left = () => {
setFirst(first <= 0 ? len : first - 1);
setSecond(second <= 0 ? len : second - 1);
setThird(third <= 0 ? len : third - 1);
};
const Right = () => {
setFirst(first >= len ? 0 : first + 1);
setSecond(second >= len ? 0 : second + 1);
setThird(third >= len ? 0 : third + 1);
};
const [first,setFirst] = useState(0);
const [second,setSecond] = useState(1);
const [third,setThird] = useState(2);
const length = SliderImages.length;
const len = length - 1;
let timeout;
useEffect(() => {
setTimeout(() => {
setFirst(first >= len ? 0 : first + 1);
setSecond(second >= len ? 0 : second + 1);
setThird(third >= len ? 0 : third + 1);
return () => clearTimeout(timeout);
},3000);
},[first,second,third]);
return (
<>
<div>
<Grid container xs={12} className={classes.grid}>
{" "}
<div>
<img
src={left}
alt="leftarrow"
className={classes.left}
onClick={Left}
/>
</div>
<Grid item xs={4} className={classes.card}>
{SliderImages.map((val,index) => {
return (
<div>
{index === first && (
<Card className={classes.card1}>
<img
src={val.imgsrc}
alt={val.title}
className={classes.image}
ref={firstRef}
/>
</Card>
)}
{index === second && (
<Card className={classes.card2}>
<img
src={val.imgsrc}
alt={val.title}
className={classes.image}
ref={secondRef}
/>
</Card>
)}
{index === third && (
<Card className={classes.card3}>
<img
src={val.imgsrc}
alt={val.title}
className={classes.image}
ref={thirdRef}
/>
</Card>
)}
<div>
<img
src={right}
alt="rightarrow"
className={classes.right}
onClick={Right}
/>
</div>
</div>
);
})}
</Grid>
</Grid>
</div>
</>
);
}
export default NewsSlider;
解决方法
问题
您的问题是当您手动更新 first
、second
或 third
之一而不清除任何先前的超时时,您又开始了另一个超时。
此外,当您在函数体中将 timeout
定义为 let timeout;
时,会在每个渲染周期重新声明它。
解决方案
捕获超时引用并从 useEffect
回调而不是在超时回调中返回清除函数。
useEffect(() => {
const timeout = setTimeout(() => {
setFirst(first >= len ? 0 : first + 1);
setSecond(second >= len ? 0 : second + 1);
setThird(third >= len ? 0 : third + 1);
},3000);
return () => clearTimeout(timeout);
},[first,second,third]);
替代方案
将滑块动画构建为间隔并使用功能状态更新来处理上一张/下一张幻灯片。功能状态更新允许您使用间隔计时器并从之前的滑动状态正确更新,同时还允许您异步手动向左或向右滑动而不会中断间隔更新。
const Left = () => {
setFirst(first => first <= 0 ? len : first - 1);
setSecond(second => second <= 0 ? len : second - 1);
setThird(third => third <= 0 ? len : third - 1);
};
const Right = () => {
setFirst(first => first >= len ? 0 : first + 1);
setSecond(second => second >= len ? 0 : second + 1);
setThird(third => third >= len ? 0 : third + 1);
};
const [first,setFirst] = useState(0);
const [second,setSecond] = useState(1);
const [third,setThird] = useState(2);
const length = SliderImages.length || 0;
const len = length - 1;
useEffect(() => {
const interval = setInterval(() => {
Right();
},3000);
return () => clearInterval(interval);
},[]);
,
我认为你需要在 useState hook 中添加箭头函数
const Left = () => {
setFirst(first => first <= 0 ? len : first - 1);
setSecond(second => second <= 0 ? len : second - 1);
setThird(third => third <= 0 ? len : third - 1);
};
const Right = () => {
setFirst(first => first >= len ? 0 : first + 1);
setSecond(second => second >= len ? 0 : second + 1);
setThird(third => third >= len ? 0 : third + 1);
};
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。