Skip to content

Instantly share code, notes, and snippets.

@jmn
Created November 22, 2018 17:43
Show Gist options
  • Save jmn/4aa6b088f34863db90d21b6b40f0d984 to your computer and use it in GitHub Desktop.
Save jmn/4aa6b088f34863db90d21b6b40f0d984 to your computer and use it in GitHub Desktop.
React Native Apollo FlatList infinite scroll
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);
@jforaker
Copy link

jforaker commented Feb 9, 2019

and here's your code with prettier

@oxbits
Copy link

oxbits commented May 19, 2019

thank for this, it helped me out!

@oguzkaganeren
Copy link

This worked for me as well, thank you for sharing!

@Ebeldev
Copy link

Ebeldev commented Oct 2, 2019

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?

@klaaz0r
Copy link

klaaz0r commented Jan 6, 2020

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