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