我在多个屏幕上使用了一个React Native组件,在其中我使用重复出现的setTimeout
函数为图像轮播设置动画。轮播效果很好,但是当从useEffect
钩子返回的回调函数中导航离开屏幕时,我想正确清除计时器。 (如果我不清除计时器,则会收到一个讨厌的错误,并且我知道我仍然应该清除计时器。)
尽管出于某种原因,我试图将setTimeout
返回的超时ID设置为从null
返回的回调中的状态变量似乎都设置为useEffect
。
这是我的代码的简化版:
const Carousel = () => {
const [timeoutId, setTimeoutId] = useState(null);
const startCarouselCycle = () => {
const newTimeoutId = setTimeout(() => {
// Code here that calls scrollToIndex for the FlatList.
}, 5000);
setTimeoutId(newTimeoutId);
};
const startNextCarouselCycle = () => {
// Other code here.
startCarouselCycle();
};
useEffect(() => {
startCarouselCycle();
return () => {
// This is called when the screen with the carousel
// is navigated away from, but timeoutId is null.
// Why?!
clearTimeout(timeoutId);
};
}, []);
return (
<FlatList
// Non-essential code removed.
horizontal={true}
scrollEnabled={false}
onMomentumScrollEnd={startNextCarouselCycle}
/>
);
};
export default Carousel;
没有人知道为什么状态无法正确更新以用于返回的useEffect
回调吗?谢谢。
您必须像这样从useEffect
钩子中删除依赖项数组:
useEffect(() => {
startCarouselCycle();
return () => {
// This is called when the screen with the carousel
// is navigated away from, but timeoutId is null.
// Why?!
clearTimeout(timeoutId);
};
});
这是因为在安装组件时触发了您的效果,并且仅获得了timeoutId
的初始值。
根据我所见,我认为没有必要将超时ID存储在状态中。试试这个:
import React, { useState, useEffect } from 'react';
import { FlatList } from 'react-native';
const Carousel = () => {
let _timeoutId = null
const startCarouselCycle = () => {
const newTimeoutId = setTimeout(() => {
// Code here that calls scrollToIndex for the FlatList.
}, 5000);
_timeoutId = newTimeoutId;
};
const startNextCarouselCycle = () => {
// Other code here.
startCarouselCycle();
};
useEffect(() => {
startCarouselCycle();
return () => {
// This is called when the screen with the carousel
// is navigated away from, but timeoutId is null.
// Why?!
clearTimeout(_timeoutId);
};
}, []);
return (
<FlatList
// Non-essential code removed.
horizontal={true}
scrollEnabled={false}
onMomentumScrollEnd={startNextCarouselCycle} />
);
};
export default Carousel;