I’m using FlashList
to display a list of item (avatar, title). While scrolling, the the wrong images of the items are shown (mixed).
According to the documentation, this happens because of the Recycling
, since FlashList
does not destroy the item when an item gets out of the viewport, but re-renders the component with a different item prop.
The component hierarchy returned from renderItem
make use of useState
(ideally component hierarchy returned from renderItem
should not make use of useState
for best performance).
const renderItem = useCallback(
({ item }: ListRenderItemInfo<Avatar>) => (
<ListItemAvatar
logoUri: getLogos(item),
id: item.name + index
/>
),
[]
);
type Avatar = {
id?: string;
logoUri?: ImageURISource | Array<ImageURISource>;
};
export const Avatar = ({ id, logoUri }: AvatarProps) => {
const indexValue = useRef<number>(0);
const lastItemId = useRef(id);
const [sourceImage, setSourceImage] = useState(
logoUri === undefined
? undefined
: Array.isArray(logoUri)
? logoUri[0]
: logoUri
);
if (id !== lastItemId.current) {
console.log(`${lastItemId.current} has been recycled to ${id}`);
lastItemId.current = id;
setSourceImage(
logoUri === undefined
? undefined
: Array.isArray(logoUri)
? logoUri[indexValue.current]
: logoUri
);
}
const onError = () => {
if (Array.isArray(logoUri) && indexValue.current + 1 < logoUri.length) {
indexValue.current = indexValue.current + 1;
setImageSource(logoUri[indexValue.current]);
return;
}
setSourceImage(undefined);
};
return (
<View>
{sourceImage === undefined ? (
<Icon />
) : (
<Image source={sourceImage} onError={onError}
/>
)}
</View>
);
};
As you can see, I reset every state when current id
does not match the lastItemId
but this does not work.
How can I fix it?
- react-native: 0.70
- @shopify/flash-list: 1.4.3