-
-
Save jmn/4aa6b088f34863db90d21b6b40f0d984 to your computer and use it in GitHub Desktop.
React Native Apollo FlatList infinite scroll
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import { Text, View, SafeAreaView, FlatList, WebView, Dimensions, Button, ScrollView} from 'react-native'; | |
import { ListItem } from 'react-native-elements'; | |
import ApolloClient from "apollo-boost"; | |
import gql from "graphql-tag"; | |
import { ApolloProvider } from "react-apollo"; | |
import { Query } from "react-apollo"; | |
import HTML from 'react-native-render-html'; | |
import { createAppContainer, createStackNavigator} from 'react-navigation'; | |
const client = new ApolloClient({ | |
uri: "https://www.fedry.net/graphql" | |
}); | |
class DetailsScreen extends React.Component { | |
render() { | |
const { navigation } = this.props; | |
const item = navigation.getParam('item', 'NO-ID'); | |
return ( | |
<ScrollView | |
style={{ flex: 1}} | |
maximumZoomScale={2} | |
> | |
<Text>{JSON.stringify(item.node.title)}</Text> | |
<HTML html={item.node.content} imagesMaxWidth={Dimensions.get('window').width -50}/> | |
</ScrollView> | |
); | |
} | |
} | |
class PostListScreen extends React.Component { | |
static navigationOptions = { | |
title: 'Fedry Reader', | |
}; | |
render() { | |
return ( | |
<App navigation={this.props.navigation} /> | |
) | |
} | |
} | |
const AppNavigator = createStackNavigator({ | |
Home: { | |
screen: PostListScreen, | |
}, | |
Details: { | |
screen: DetailsScreen, | |
}, | |
}, { | |
initialRouteName: 'Home', | |
}); | |
const App = ({navigation}) => ( | |
<ApolloProvider client={client}> | |
<ExchangeRates navigation={navigation}/> | |
</ApolloProvider> | |
); | |
mySeparator = () => ( | |
<View | |
style={{ | |
height: 1, | |
width: '100%', | |
backgroundColor: "#CED0CE" | |
}} | |
/> | |
); | |
const PostsQuery = gql` | |
query( $cursor: String) | |
{ | |
posts(first: 20, after: $cursor) { | |
edges { | |
node { | |
title | |
id | |
content | |
} | |
} | |
pageInfo { | |
startCursor | |
endCursor | |
} | |
} | |
} | |
` | |
const ExchangeRates = ({navigation}) => ( | |
<Query query={PostsQuery} > | |
{({ loading, error, data, fetchMore }) => { | |
if (loading) return <Text>Loading...</Text>; | |
if (error) return <Text>Error </Text>; | |
return <FlatList | |
data={data.posts.edges} | |
renderItem={({item})=><ListItem id={item.node.id} title={item.node.title} titleNumberOfLines={0} subtitleNumberOfLines={10} onPress={() => {navigation.navigate('Details', {item: item})}} />} | |
keyExtractor={(item, index) => index.toString()} | |
ItemSeparatorComponent={this.mySeparator} | |
onEndReachedThreshold={1} | |
onEndReached={() => { | |
console.log('end'); | |
console.log(data.posts.pageInfo); | |
console.log(fetchMore); | |
fetchMore({ | |
variables: { cursor: data.posts.pageInfo.endCursor }, | |
updateQuery: (previousResult, { fetchMoreResult }) => { | |
const newEdges = fetchMoreResult.posts.edges; | |
const pageInfo = fetchMoreResult.posts.pageInfo; | |
console.log(previousResult.posts); | |
// return { posts: [...previousResult.posts.edges, ...fetchMoreResult.posts.edges] }; | |
return newEdges.length | |
? { | |
// Put the new comments at the end of the list and update `pageInfo` | |
// so we have the new `endCursor` and `hasNextPage` values | |
posts: { | |
__typename: previousResult.posts.__typename, | |
edges: [...previousResult.posts.edges, ...newEdges], | |
pageInfo | |
} | |
} | |
: previousResult; | |
} | |
}) | |
} | |
} | |
/> | |
}} | |
</Query> | |
); | |
export default createAppContainer(AppNavigator); |
Thanks for this. It helped me a lot. But once I reach the end of the full list (there is no more items to fetch) , I get the spinner and it never stops spinning.
Any idea?
You want to include a hasNext
or something simpler in your api, and don't render fetch/disable fetch more when hasNext
is false, you can also include a footer when hasNext
is false and inform the user they have seen it all.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks for this. It helped me a lot. But once I reach the end of the full list (there is no more items to fetch) , I get the spinner and it never stops spinning.
Any idea?