RefreshControl 数据重复每次在 React Native 中拉动以刷新 ScrollView

Posted

技术标签:

【中文标题】RefreshControl 数据重复每次在 React Native 中拉动以刷新 ScrollView【英文标题】:RefreshControll data duplicate everytime do pull to refresh on ScrollView in React native 【发布时间】:2020-11-05 07:30:26 【问题描述】:

说明 我在 React Native 中使用 RequestController 实现了一个拉取请求,每次我拉动刷新相同的数据时,都会一遍又一遍地添加到平面列表中。我不是在平面列表中实现拉取请求,而是在包裹FlatListScrollView 上实现。

操作

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>
          );
    /> 

输出 每次触发新的拉取刷新时都会复制数据

【问题讨论】:

这很有意义......因为您将新结果连接到当前结果列表中,状态为this.setState(results: [...this.state.results, response.data]); 如何解决这个@Hend El-Salhi 我是 React Native 新手,你能告诉我解决这个问题的简单方法吗? 查看下面的答案... 【参考方案1】:

我假设您的 api 调用会返回整个产品列表

此行将 api-response-data 连接到您在组件状态中已有的产品列表

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

试试这个吧……

this.setState( results: response.data );

【讨论】:

我已经试过了,我将我的结果连接起来,因为它们是我的 api 调用返回的一个复杂的承诺,这就是我想将它们放在一个新数组中的原因。有什么方法可以将它们放在新数组中而不像以前那样连接? 你能 console.log 这个console.log(await response.data) 吗? 感谢您的帮助,您已经给了我有用的提示。我很感激。【参考方案2】:

您应该替换您的数据而不是连接。使用:

this.setState( results: response.data );

另外,您应该使用 FlatList 'onRefresh' 属性来实现刷新功能,而不是在父级上使用额外的 ScrollView。

【讨论】:

我知道这一点,但是问题是我从 api-call 返回的是包含 id 和属性的对象,所以我必须使用我的渲染函数下的一些步骤删除 id,所以我决定将它们放入新数组中。 感谢您的帮助,您已经给了我有用的提示。我很感激。 那么在这种情况下有一个更好的方法。您应该保持键值对原样并生成一个新的 id 数组并将其提供给 FlatList。然后在 renderItem 中,您将获得密钥作为项目,因此您可以使用该密钥从主对象简单地访问该对象,例如: renderItem(item) const gameItem = this.state.results[item] 这样您的数据将更易于管理且易于访问【参考方案3】:

哦,我找到了办法。我只需要这样做。 this.setState(results: [response.data]);

【讨论】:

【参考方案4】:

我遇到了和你一样的问题, 我刷新的时候,数据是(data)+[(data)+(new_data)]。

这里发生的是数据被添加到这个变量的数组中:结果。 为防止这种情况,您必须首先清除此变量:results。 所以您的代码将如下所示。

state = 
        refreshing: false,

        results : [],   

当 API 运行时,这个数组将填充 results[some_data,some_data,some_data,..]

刷新时-> 第一个:结果将为空, 第二:使用 API 中新添加的数据重新分配该数组。

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

【讨论】:

以上是关于RefreshControl 数据重复每次在 React Native 中拉动以刷新 ScrollView的主要内容,如果未能解决你的问题,请参考以下文章

UIRefreshControl 重复出现

ReactNative进阶(十七):RefreshControl组件实现刷新效果

ReactNative进阶(十七):RefreshControl组件实现刷新效果

使用 RefreshControl 异步刷新

React Native refreshControl 在下拉之前显示

如何抵消 RefreshControl