I wanted to use an animated Flatlist to extract the scroll offset and use it to hide and show my header,
but i got an error:
Invariant violation: element type is invalid: expect a string or class/function but got undefined.
import React from 'react';
import {Text, View, Button} from 'react-native';
import Animated from 'react-native-reanimated';
const Screen= props=> {
return (
<View>
<Button
title= "Go back"
onPress= {() => props.navigation.goBack()}
/>
<Text>This is the Test screen</Text>
<Animated.Flatlist />
</View>
);
}
Screen.navigationOptions = ({navigation}) => {
return {title: 'Test'}
}
export default Screen;
Any suggestion it doesn't work with Flatlist, knowing that if i change Animatet.Flatlist to Animated.Scrollview it works.
pass prop renderScrollComponent
ShaMan123
These are the props i pass to my flatlist:
<Animated.FlatList
scrollEventThrottle= {16}
onScroll= {Animated.event(
[
{nativeEvent: {contentOffset:{y: scrollY}}}
],
{ useNativeDriver: true }
)}
style= {{paddingHorizontal: 15, paddingTop: 70}}
contentContainerStyle= {{paddingBottom: 75}}
bounces= {false}
alwaysBounceVertical= {false}
data= {names}
renderItem= {({item})=>
<View style= {{paddingVertical: 10, marginBottom: 10}}>
<Text>{item}</Text>
</View>
}
keyExtractor= {item=> item}
/>
Do i need to pass renderScrollComponent
try passing all scroll related props through renderScrollComponent:
<FlatList
{...props}
renderScrollComponent={(props) => <ScrollView {...props} {...moreProps} />}
/>
Hi @achrafKara,
did the solution presented by @ShaMan123 solve your issue?
@jakub-gonet yes it did
I'd like to reopen this.
While using the renderScrollComponent _does_ work, it doesn't allow all props to work.
If you use the renderScrollComponent with an onScroll prop for the Animated.ScrollView, the onViewableItemsChanged callback never fires after the first time when the component mounts.
import * as React from 'react'
import { FlatList, Dimensions } from 'react-native'
import Animated from 'react-native-reanimated'
import { onScroll } from 'react-native-redash'
export default () => {
const itemHeight = Dimensions.get('window').height
return (
<FlatList
data={data}
renderItem={renderItem}
keyExtractor={(_, index) => index.toString()}
renderScrollComponent={props => (
<Animated.ScrollView
{...props}
// 馃憞if you comment this in, onViewableItemsChanged won't fire.
// onScroll={onScroll({ y: feedScroll })}
// 馃憞same goes if you comment this in
// onScroll={() => null}
/>
)}
pagingEnabled
getItemLayout={(_, index) => {
return {
length: itemHeight,
index,
offset: index * itemHeight
};
}}
showsVerticalScrollIndicator={false}
onViewableItemsChanged={console.log} // only logs the first time
viewabilityConfig={viewabilityConfig}
/>
)
}
const viewabilityConfig = {
itemVisiblePercentThreshold: 80
};
@nandorojo It seems that's because you overwrite the default props.onScroll set by the FlatList itself, which allows it to know when to trigger onViewableItemsChanged.

Not sure why I didn't think of this sooner. I haven't tried this since I moved on from this project, but I have a feeling this will fix it:
<FlatList
renderScrollComponent={(props) => (
<Animated.ScrollView
{...props}
onScroll={(event) => {
onScroll({ y: feedScroll })(event)
props.onScroll(event)
}}
/>
)}
/>
Full example:
import * as React from 'react'
import { FlatList, Dimensions } from 'react-native'
import Animated from 'react-native-reanimated'
import { onScroll } from 'react-native-redash'
export default () => {
const itemHeight = Dimensions.get('window').height
return (
<FlatList
data={data}
renderItem={renderItem}
keyExtractor={(_, index) => index.toString()}
renderScrollComponent={(props) => (
<Animated.ScrollView
{...props}
onScroll={(event) => {
onScroll({ y: feedScroll })(event)
props.onScroll(event)
}}
/>
)}
pagingEnabled
getItemLayout={(_, index) => {
return {
length: itemHeight,
index,
offset: index * itemHeight
}
}}
showsVerticalScrollIndicator={false}
onViewableItemsChanged={console.log} // only logs the first time
viewabilityConfig={viewabilityConfig}
/>
)
}
const viewabilityConfig = {
itemVisiblePercentThreshold: 80
}
@nandorojo just a small typo, i think you meant to import import { onScrollEvent } from "react-native-redash"
However, I couldn't make it work with onScrollEvent so I replaced it with the reanimated event and it works:
renderScrollComponent={ (props) => (
<Animated.ScrollView
{ ...props }
onScroll={ Animated.event(
[
{ nativeEvent: { contentOffset: { y } } }
],
{ useNativeDriver: true }
) }
/>
) }
Most helpful comment
I'd like to reopen this.
While using the
renderScrollComponent_does_ work, it doesn't allow all props to work.If you use the
renderScrollComponentwith anonScrollprop for theAnimated.ScrollView, theonViewableItemsChangedcallback never fires after the first time when the component mounts.