'RefreshControll data duplicate everytime do pull to refresh on ScrollView in React native

Description
I implement a pull request using RequestController in React Native, every time I did pull to refresh the same data keep adding on in Flat list over and over. I implemented pull request not inside the Flat list but on the ScrollView which wrapped the FlatList.

Actions

import React, { Component } from 'react';
import { View, StyleSheet, Text, Button, Modal, Dimensions, ScrollView, TextInput, TouchableOpacity, StatusBar, Image, Platform, TouchableNativeFeedback,FlatList, ImageBackground, RefreshControl } from 'react-native';
import axios from 'axios';
class HomeScreen extends Component{
    state = {
        refreshing: false,
    }
    componentDidMount(){
        this.searchApi();
    }
    searchApi = async() => {
        const response = await axios.get('http://73udkYid.ngrok.io/api/v1/products',{
                headers: {
                    "x-auth-token":"eyJfaWQiOiI1ZdfjzZmM4YjIwYjBjZDQyMmJkNzUiLCJpYXQiOjE2MD"
                }
            }
        );
        this.setState({results: [...this.state.results, response.data]});
    }
    _onRefresh = () => {
        this.setState({refreshing: true});
        this.searchApi().then(() => {
          this.setState({refreshing: false});
        });
    }
    render(){
        let finalGames = [];
            this.state.results.forEach(obj => {
                Object.keys(obj).forEach(key => {
                finalGames.push(obj[key]);
            });
        });
        return (
        <ScrollView style={{flex: 1,backgroundColor: 'white',}}
                refreshControl = {
                    <RefreshControl 
                        refreshing = { this.state.refreshing }
                        onRefresh={this._onRefresh}
                    />
                }
            >  
       
        <FlatList 
            data = { finalGames }
            keyExtractor = {(item, index) => index.toString()}
            renderItem = { ({item: itemData}) => {
                if(itemData.empty == true){
                    return <View style = {[styles.item,styles.itemInvisible]}/>
                }
                return (
                    <View style = {{ flex: 1, margin: 4}}>
                    <View style = {styles.item}> 
                    <TouchableOpacity 
                        onPress = {() => {
                            this.setState({ viewController: this.state.viewController++ })
                            this.props.navigation.navigate(
                                "ProductDetail", {
                                itemDataDetail: itemData,
                                businessname:this.props.navigation.state.params.businessname,
                                viewController: this.state.viewController,
                             })
                         }}>
                    <View>
                        <ImageBackground 
                            source={{ uri: itemData.photo }}
                            style={{ width:'100%',aspectRatio: 1, borderRadius: 15, borderWidth:1, borderColor:"#FAFAFA", overflow: 'hidden'}}>
                        </ImageBackground>
                        <View style = {{ margin: 5}}>
                        <Text style = {{color: '#2E2E2E', fontWeight:"bold"}} numberOfLines={1}>{itemData.item}</Text>
                        <Text style = {{color: '#2E2E2E', fontSize: 12, fontWeight:"normal", alignSelf: 'flex-start'}} numberOfLines={1}>Available now | Sold out</Text>
                        <Text style = {{color: 'white', fontSize: 18, fontWeight:"bold", backgroundColor:"#DE1F38", alignSelf: 'flex-start', paddingHorizontal: 10,paddingVertical:2,borderRadius: 8,overflow: 'hidden', marginTop: 5}} numberOfLines={1}>${itemData.price}</Text>
                    </View>
                    </View>
                    </TouchableOpacity>
                    </View>
                    </View>
            </ScrollView>
          );
    }}/> 
}

Output
Data duplicated every time new pull refresh triggered



Solution 1:[1]

I assume your api-call returns the whole list of products

This line concat api-response-data to the the list of products you already have in your component-state

this.setState({results: [...this.state.results, response.data]});

Try this instead...

this.setState({ results: response.data });

Solution 2:[2]

You should replace your data instead of concatenating. Use:

this.setState({ results: response.data });

Also, you should use FlatList 'onRefresh' prop to implement refresh functionality instead of using an extra ScrollView on the parent.

Solution 3:[3]

I was facing the same problem as you, When I refreshed, the data was (data)+[(data)+(new_data)].

What happens here is that data is added to the array of this variable: results. To prevent this you must first clear this variable: results. So your code will look like this.

state = {
        refreshing: false,

        results : [],   
}

when API runs, this array will filled results[{some_data},{some_data},{some_data},..],

While you refresh-> 1st: The results will Empty, 2nd: reassign that array with newly added data from API.

_onRefresh = () => {
        this.setState({results: []});
        this.setState({refreshing: true});
        this.searchApi().then(() => {
          this.setState({refreshing: false});
        });
    }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Hend El-Sahli
Solution 2 Muhammad Umer Qadri
Solution 3 Ashish Pipaliya