[英]Reactjs unexpected useState behaviour in slider
我使用 useEffect 实现了自动播放 Slider(具有三张卡),但手动“上一个”和“前进”按钮无法正常工作。 useState 没有根据需要更新值。 useState 正在改变我无法理解这种随机行为的值。 一旦我单击上一个或向前箭头滑动幻灯片,它就会开始非常快速地更改幻灯片。 自动 slider 运行良好,但我手动滑动而不是使用状态意外更改值。 我如何实现自动和手动(前进和后退箭头),以便 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
之一而不清除任何先前的超时时,您会开始另一个超时。
此外,当您在 function 主体中将超时定义为 let timeout
时,每个渲染周期都会重新声明let timeout;
.
捕获 timeout ref 并从useEffect
回调而不是 timeout 回调中返回清除 function。
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]);
将 slider animation 构造为在间隔上,并使用功能 state 更新来处理上一张/下一张幻灯片。 功能 state 更新允许您使用间隔计时器并从上一张幻灯片 state 正确更新,同时还允许您异步手动向左或向右滑动而不中断间隔更新。
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 挂钩中添加箭头 function
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);
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.