74

please help me out to implement pull to refresh on my app, I'm kinda new to react native, thanks. I don't know how to handle onRefresh and refreshing.

class HomeScreen extends Component {
  state = { refreshing: false }

  _renderItem = ({ item }) => <ImageGrid item={item} />

  _handleRefresh = () => {

  };

  render() {
    const { data } = this.props;
    if (data.loading) {
      return (
        <Root>
          <Loading size="large" />
        </Root>
      )
    }
 return (
   <Root>
     <HomeHeader />
     <FlatList
       contentContainerStyle={{ alignSelf: 'stretch' }}
       data={data.getPosts}
       keyExtractor={item => item._id}
       renderItem={this._renderItem}
       numColumns={3}
       refreshing={this.state.refreshing}
       onRefresh={this._handleRefresh}
     />
   </Root>
  );
 }
}

export default graphql(GET_POSTS_QUERY)(HomeScreen);

10 Answers 10

112

Set variable

this.state = { 
    isFetching: false,
}

Create Refresh function

onRefresh() {
    this.setState({isFetching: true,},() => {this.getApiData();});
}

And in last set onRefresh and refreshing in FlatList.

<FlatList
    data={ this.state.FlatListItems }
    onRefresh={() => this.onRefresh()}
    refreshing={this.state.isFetching}
/>

After fetching Data in function getApiData Make sure to set false isFetching.

this.setState({ isFetching: false })
4
  • Hey @Krish i do it , but last item in Data it can't disappear and when i pull to refresh the "loading" stuck and can't get new data!
    – DevAS
    Commented Nov 8, 2019 at 13:10
  • @DevAS Empty the array(when you setstate blank array flatlist must reload) before calling reload function and check if still your FlatList is showing last item or not.
    – krish
    Commented Nov 8, 2019 at 14:01
  • I don't understand what you mean :/ you said empty the array when call onRefresh?
    – DevAS
    Commented Nov 8, 2019 at 14:33
  • @DevAS I mean Empty the array (in my example "FlatListItems"), it must refresh the Flatlist and should not show the last the last item. Please share code so that i can review it.
    – krish
    Commented Nov 11, 2019 at 6:05
29

You can also use refreshControl in Flatlist, ScrollView, and any other list component.

<FlatList
  contentContainerStyle={{ alignSelf: 'stretch' }}
  data={data.getPosts}
  keyExtractor={(item) => item._id}
  renderItem={this._renderItem}
  numColumns={3}
  refreshControl={
    <RefreshControl
      refreshing={this.state.refreshing}
      onRefresh={this._handleRefresh}
    />
  }
/>
    
1
  • if you set <FlatList /> prop onRefresh, FlatList will set RefreshControl automatically, althouth it's a default one.
    – Bruce Lee
    Commented Dec 18, 2017 at 6:25
15

If someone is interested in doing it with React Hooks here is it:

First create isRefreshing state:

const [isRefreshing, setIsRefreshing] = useState(false)

Then create your onRefresh function that calls API to refresh data:

const onRefresh = () => {
    //set isRefreshing to true
    setIsRefreshing(true)
    callApiMethod()
    // and set isRefreshing to false at the end of your callApiMethod()
}

And after that, your FlatList component that looks like that:

return (
    <FlatList
        style={styles.flatList}
        onRefresh={onRefresh}
        refreshing={isRefreshing}
        data={data}
        renderItem={renderItem}
        keyExtractor={item => item.id.toString()}
    />
)
10

// Sample code representing pull to refresh in flatlist. Modify accordingly.

import React, { Component } from 'react'
    import { Text, View,StyleSheet,FlatList,Dimensions,Image,TouchableHighlight } from 'react-native'

    export default class Home extends Component {

        constructor(props) 
        {
            super(props);
        this.state = {
            data : [],
            gender : "",
            isFetching: false,
        }
        }

    componentWillMount()
    {

        this.searchRandomUser()
    }

    onRefresh() {
        this.setState({ isFetching: true }, function() { this.searchRandomUser() });
     }

    searchRandomUser = async () =>
    {
       const RandomAPI = await fetch('https://randomuser.me/api/?results=20')
       const APIValue = await RandomAPI.json();
        const APIResults = APIValue.results
          console.log(APIResults[0].email);
          this.setState({
              data:APIResults,
              isFetching: false
          })

    }

      render() {
        return (
          <View style = {styles.container}>
     <TouchableHighlight
     onPressOut = {this.searchRandomUser}
         style = {{width:deviceWidth - 32, height:45,backgroundColor: 'green',justifyContent:"center",alignContent:"center"}}>
              <Text style = {{fontSize:22,color: 'white',fontWeight: 'bold',textAlign:"center"}}>Reload Data</Text>
         </TouchableHighlight>
     <FlatList
            data={this.state.data}
            onRefresh={() => this.onRefresh()}
          refreshing={this.state.isFetching}
            keyExtractor = { (item, index) => index.toString() }
            renderItem={({item}) =>
            <View style = {styles.ContainerView}>
            <View>
    <Image
    source={{uri : item.picture.large}}
    style = {{height:100,width:100,borderRadius: 50,marginLeft: 4}}
    resizeMode='contain'
    />
    </View>

    <View style = {{flexDirection: 'column',marginLeft:16,marginRight: 16,flexWrap:'wrap',alignSelf:"center",width: deviceWidth-160}}>
    <Text>Email Id : {item.email}</Text>

    <Text>Full Name : {this.state.gender} {item.name.first} {item.name.last}</Text>
    <Text>Date of birth : {item.dob.age}</Text>
    <Text>Phone number : {item.phone}</Text>

    </View>

    </View>
            }
            />
          </View>
        )
      }
    }
    const deviceWidth = Dimensions.get('window').width
    const deviceHeight = Dimensions.get('window').height
    const styles = StyleSheet.create({
        container: {
          flex: 1,
          alignItems: 'center',
          justifyContent: 'center',
          marginTop:22
        },
        ContainerView:
        {
            // backgroundColor:'grey',
            marginBottom:20,
            paddingVertical:10,
            backgroundColor: '#F5F5F5',

            borderBottomWidth:0.5,
            borderBottomColor:'grey',
            width: deviceWidth-40,
            marginLeft:20,
            marginRight:20,
            marginTop:20,
            flexDirection:'row'
        }
      });
1
8
const [refreshing, setRefreshing] = useState(false)
    
 <FlatList
     style={{ padding: 15 }}
     refreshControl={
         <RefreshControl 
             refreshing={refreshing} 
             onRefresh={_onRefresh}
             tintColor="#F8852D"/>
     }
     showsVerticalScrollIndicator={false}
     data={listData}
     renderItem={renderItem}
     item={(item, index) => index.toStirng()}
     onEndReachedThreshold={0.8}
     onEndReached={() => onEndReached()}
     ListFooterComponent={() => renderFooter()}
 /> 

_onRefresh Function

const _onRefresh = () => {
    console.log('_onRefresh')
    setRefreshing(true);
    getPosts();
};
3
  • 1
    refreshing and onRefresh are already FlatList props. Do you still need to wrap in it a RefreshControl tag?
    – ahron
    Commented Jul 21, 2021 at 14:45
  • @deepanshu please correct the spelling of index.toStirng() to index.toString() Commented Oct 6, 2021 at 17:55
  • import { RefreshControl } from 'react-native'; Commented Mar 10, 2023 at 7:53
1

"Pull to refresh" concept implies that the list can be manually refreshed thus can be changed outside the current view (e.g. fetched from server). So the callback onRefresh has to trigger the data reloading process (e.g. send a request to the server) and set the refreshing variable to truthy value. This will notify the user that the process was started by showing loading indicator. Once you got the data ready you need to set refreshing to falsy so the view will hide loading indicator.

1

this is the best that I can do. my Code Image

when I pull it down it dosen't refetch data from server I'm running graphql server which connected by Apollo to the app, and I don't know how to get data from server in _getData() function.

1
  • It would be helpful if you paste the code snippet here. Commented Dec 17, 2020 at 11:10
1

Instead of using pull to refresh on flat-list simply use on Scroll View.

Set Refresh State

this.state = { 
     isFetching: false,
  }

Set onFresh in ScrollView

<ScrollView
  refreshControl={
    <RefreshControl
      refreshing={this.state.refresh}
      onRefresh={() => this.onRefresh()}
      tintColor="red"
    />
  }>
  <FlatList data={data} renderItem={this._renderItem} numColumns={3} />
</ScrollView>;

In OnRefreshFunction

  onRefresh() {
    this.setState({refresh: true});
    setTimeout(() => {
      this.setState({refresh: false});
    }, 2000);
  }
1
  • The question is specifically for how to do it for FlatList, not what the alternatives to FlatList are.
    – ahron
    Commented Jul 21, 2021 at 14:43
1

You can check the official document:

https://reactnative.dev/docs/refreshcontrol

1

For anyone looking for an updated answer using new React Hooks.

You can use isLoading and refetch from useQuery. Then use RefreshControl with FlatList. Read more on RefreshControl: https://reactnative.dev/docs/refreshcontrol

const RenderImageGrid = (item) => <ImageGrid item={item} />

export const HomeScreen = () => {
    const { data, isLoading, refetch } = useQuery('get_home_screen_data', GET_HOME_SCREEN_DATA)
    return (
        {isLoading ? (
            <Root>
                <Loading size="large" />
            </Root>
        ) : (
            <Root>
                <HomeHeader />
                <FlatList
                    data={data}
                    keyExtractor={item => item._id}
                    renderItem={RenderImageGrid}
                    numColumns={3}
                    refreshControl={
                        <RefreshControl 
                            refreshing={isLoading}
                            onRefresh={refetch} 
                        />
                    }
                />
            </Root>
        )}
    )
}

export default HomeScreen

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.