我正在尝试使轮播与某些动画互动。我已经设置了一些状态来更改当前渲染的子级+是否应显示淡入淡出过渡。
我遇到了一些问题
setTimeout
和next()
内部的previous()
会触发,并且在卸载组件后,我会收到有关状态更改的控制台错误。 / li>
我已经将start()
和stop()
重构为使用intervalRef
,并且我感到将超时转换为timeoutRef
可以解决这两个问题,但是我不确定如何
type Props = {
interval?: number;
timeout?: number;
children: React.ReactNodeArray;
}
const Carousel: React.FC = ({ interval = 4000, timeout = 500, children }) => {
const [fade, setFade] = useState(true); // Start fade animation
const [childIndex, setChildIndex] = useState(0); // Which child to render
const intervalRef = useRef<NodeJS.Timer | null>(null);
const next = useCallback(() => {
setFade(false); // do the fade out animation
setTimeout(() => {
setChildIndex((pIndex) => (pIndex + 1) % children.length); // update which to display
setFade(true); // display fade in animation
}, timeout);
}, [timeout, children]);
const previous = useCallback(() => {
setFade(false); // do the fade out animation
setTimeout(() => {
setChildIndex((pIndex) => ((pIndex - 1) + children.length) % children.length); // update which to display
setFade(true); // display fade in animation
}, timeout);
}, [timeout, children]);
const start = useCallback(() => {
if (intervalRef.current === null) {
intervalRef.current = setInterval(next, interval);
}
}, [next, interval]);
const stop = useCallback(() => {
if (intervalRef.current !== null) {
clearInterval(intervalRef.current);
intervalRef.current = null;
}
}, []);
useEffect(() => {
start();
return () => stop();
}, [start, stop]);
return (
<>
<Fade in={fade} timeout={timeout} onMouseEnter={stop} onMouseLeave={start}> // don't switch item on hover
<div>
{children[childIndex]}
</div>
</Fade>
<Button onClick={previous}>Previous</Button>
<Button onClick={next}>Next</Button>
</>
)
}
答案 0 :(得分:-1)
setTimeout
应该真正在Effect
内部调用,以便在卸载组件时可以clearTimeout
。
遵循以下原则:
useEffect(() => {
const tId = setTimeout(() => {
// do stuff
}, 500);
return () => clearTimeout(tId);
}, []);
要处理“键盘粉碎用户”问题,请查看debouncing或throttling您的事件处理程序