Данные refreshControl дублируются каждый раз, когда выполняется извлечение для обновления в ScrollView в React native

#javascript #react-native #uirefreshcontrol

#javascript #react-native #uirefreshcontrol

Вопрос:

Описание
Я реализую запрос на извлечение, используя RequestController в React Native, каждый раз, когда я выполнял извлечение для обновления одних и тех же данных, продолжайте добавлять в плоский список снова и снова. Я реализовал запрос на извлечение не внутри плоского списка, а в ScrollView том, который обернул FlatList .

Действия

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

Вывод
Данные дублируются при каждом запуске нового обновления

Комментарии:

1. Это имеет смысл… потому что вы связываете новый результат с текущим списком результатов, сохраненным в состоянии this.setState({results: [...this.state.results, response.data]});

2. Как решить эту проблему @Hend El-Salhi

3. Я новичок в React Native, можете ли вы сказать мне простой способ решить эту проблему?

4. Проверьте ответ ниже…

Ответ №1:

Я предполагаю, что ваш api-вызов возвращает весь список продуктов

Эта строка объединяет api-response-data со списком продуктов, которые у вас уже есть в вашем компонентном состоянии

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

Попробуйте это вместо этого…

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

Комментарии:

1. Я уже пробовал это, я объединяю свои результаты, потому что это сложный возврат обещания из моего api-вызова, поэтому я хочу поместить их в новый массив. Могу ли я каким-либо образом поместить их в новый массив без объединения, как я делал ранее?

2. Не могли бы вы утешить. регистрировать это console.log(await response.data) ?

3. Спасибо за вашу помощь, вы уже дали мне полезный совет. Я ценю это.

Ответ №2:

Вы должны заменить свои данные вместо объединения. Используйте:

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

Кроме того, вы должны использовать опору FlatList ‘onRefresh’ для реализации функции обновления вместо использования дополнительного ScrollView для родительского элемента.

Комментарии:

1. Я знаю об этом, однако проблема заключается в том, что мой возврат из api-вызова является объектом, который содержит идентификатор и свойства внутри, поэтому мне нужно удалить идентификатор, выполнив несколько шагов в моей функции рендеринга, поэтому я решаю поместить их в новый массив.

2. Спасибо за вашу помощь, вы уже дали мне полезный совет. Я ценю это.

3. Что ж, в этом случае есть более эффективный способ. Вы должны сохранить пару ключ-значение как есть, сгенерировать новый массив идентификаторов и предоставить его в 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},..] ,

Пока вы обновляете-> 1st: результаты будут пустыми, 2nd: переназначите этот массив новыми добавленными данными из API.

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