Description
Is there an existing issue for this?
- I have searched the existing issues
Edit: #2566 may be related
Describe the issue
Hello, I recently upgraded from 18.11 to 19.6, and I noticed that some of my components that use FlatList and rely on viewabilityConfig
were no longer working properly. It seems onViewableItemsChanged stops working in some very specific cases. In the repro I provide, viewability breaks when I run Animated.loop on an animation that has useNativeDriver set to false, and after changing state on the data being rendered by the FlatList.
However, after fixing the issue by setting useNativeDriver: true on the animation that was causing it, I found that other areas of my app where also causing viewability to break even though I had no other instances of Animated.loop being called, so clearly this is not the only case that can cause this viewability issue to occur.
This is important for us because we rely on viewabilityConfig to determine when videos in a flatlist should stop/start playing.
Thanks for the great work bringing react native to the web!
Expected behavior
For onViewableItemsChanged
to be called as expected, regardless of whether an animation is running in another part of the app
Steps to reproduce
- Create FlatList with viewability config props passed in:
<FlatList
data={data}
horizontal
renderItem={({ item, index: idx }) =>
renderItem({
item,
index,
isViewable: viewableItemIndices.includes(idx),
})
}
viewabilityConfigCallbackPairs={
viewabilityConfigCallbackPairs.current
}
/>
with the following values for viewabilityConfigCallbackPairs
:
const VIEWABILITY_CONFIG = {
viewAreaCoveragePercentThreshold: 50,
};
function MyComponent() {
...
...
const [viewableItemIndices, setViewableItemIndices] = useState<number[]>([]);
const viewabilityConfigCallbackPairs = useRef([
{
viewabilityConfig: VIEWABILITY_CONFIG,
onViewableItemsChanged: (info: {
viewableItems: ViewToken[];
changed: ViewToken[];
}) => {
console.log(
'called',
info.viewableItems.map((item) => item.index as number),
);
setViewableItemIndices(
info.viewableItems.map((item) => item.index as number) || [],
);
},
},
]);
...
- Start an animation loop with useNativeDriver: false
useEffect(() => {
animationLoop.current = Animated.timing(animationRef.current, {
toValue: 2,
duration: 1500,
useNativeDriver: false
});
animationRef.current.setValue(0);
Animated.loop(animationLoop.current).start();
}, []);
- Make a state change on the data being rendered by FlatList, changing the length of the array:
setData([...])
- Note how the console.log() call in onViewableItemsChanged is never reached
Test case
https://codesandbox.io/s/weird-virtualizedlist-2rc2ln?file=/src/App.js
Additional comments
I am not familiar with React Native internals, so I just hope this repro can point you to the root cause and help solve this problematic issue. Thank you!!