Reputation: 645
I am using Redux to fetch data and add it to the store and after adding it i tried to view the result in a Flat List but the following error message appear in logger
and i searched for a while and i got the fact that i have to use conditions to prevent Flat List from rendering before data fetched and get added to the store, so i tried to assign my data list to my local component state with componentWillReceiveProps to force the component to rerender and view the list of data in Flat List but suddenly the same error appear although i already used conditions that make Flat List wait till data received and saved to store .
the data is looks like the following
homePage.js that contain Flat List
import React from 'react';
import { Text, View, ScrollView, TouchableOpacity, FlatList } from 'react-
native';
import {Container, Header, Content, Item, Input, Button} from 'native-base';
import RPostCard from './reusablePostCard';
import FontAwesome5 from 'react-native-vector-icons/FontAwesome5';
import Foundation from 'react-native-vector-icons/Foundation';
class HomePage extends React.Component {
constructor(props){
super(props);
this.state = {
postsData: []
}
}
componentDidMount(){
this.props.getNewsFeedPosts();
}
componentWillReceiveProps(nextProps){
if (nextProps.postsData !== this.props.postData){
this.setState({postsData: nextProps.postsData})
}
}
render() {
let { postsData, postsFetched } = this.props;
return (
<View style={styles.container}>
<Header style={styles.header}>
<View style={styles.messagesIconView}>
<TouchableOpacity onPress={() => this.props.navigation.navigate('Chat')}>
<FontAwesome5 name='comment' size={23} color='#ffffff'/>
</TouchableOpacity>
</View>
<View style={styles.telephoneIconView}>
<TouchableOpacity>
<Foundation name='telephone' size={25} color='#ffffff'/>
</TouchableOpacity>
</View>
<Content style={styles.searchContent}>
<Item style={styles.searchItem}>
<Input placeholder='ابحث هنا' placeholderTextColor='#ffffff' style={styles.inputValueStyle}/>
<FontAwesome5 name='search' size={15} color='#ffffff' style={styles.searchIconStyle}/>
</Item>
</Content>
</Header>
{(this.state.postsData.length === 0) ?
null
:
<ScrollView>
<FlatList
data={this.state.postsData}
renderItem={({postData}) => (<Text>{postData.title}</Text>)}
/>
</ScrollView>
}
</View>
);
}
}
HomePage.defaultProps = {
}
export default HomePage;
Home Container which contain mapstatetoprops & mapActionCreators
import {connect} from "react-redux";
import HomePage from "../../components/HomeScreens/HomePage";
import {
getNewsFeedPosts
} from "../../modules/Home";
const mapStateToProps = (state) =>({
postsData: state.Home.posts,
postsFetched: state.Home.postsFetched,
});
const mapActionCreators = {
getNewsFeedPosts
};
export default connect(mapStateToProps, mapActionCreators)(HomePage);
Action Handler function that componentdidmount() call in HomePage.js
function handleNewsFeedPosts(state, action){
const postsData = action.payload.data.posts;
const likesNo = action.payload.data.likes;
const commentsNo = action.payload.data.comments;
const post = {};
var posts = [];
var postsIds = [];
var imageLink = "http://192.168.1.117:3000/image/";
var month_ar = '';
var month_en = '';
var oldPostsState = [];
var oldPostsIdsState =[];
for (i = 0; i < postsData.length; i++) {
//filter description from <p> </p> tags
const description = postsData[i].description;
const filteredDescription = description.replace(/<[^>]*>/g, '');
//filter date and time from '-' and split date and time converting it to arabic
const created_at = postsData[i].created_at.replace(/-/g, ' ');
created_at = postsData[i].created_at.replace(/:/g, ' ');
const created_at_filter = postsData[i].created_at.split(' ');
const date = created_at_filter[0].split('-');
const month = parseInt(date[1]);
switch (month) {
case 1:
month_en = " January ";
month_ar = " يناير ";
break;
case 2:
month_en = " February ";
month_ar = " فبراير ";
break;
case 3:
month_en = " March ";
month_ar = " مارس ";
break;
case 4:
month_en = " April ";
month_ar = " ابريل ";
break;
case 5:
month_en = " May ";
month_ar = " مايو ";
break;
case 6:
month_en = " June ";
month_ar = " يونيو ";
break;
case 7:
month_en = " July ";
month_ar = " يوليو ";
break;
case 8:
month_en = " August ";
month_ar = " أغسطس ";
break;
case 9:
month_en = "September";
month_ar = "سبتمبر";
break;
case 10:
month_en = " October ";
month_ar = " أكتوبر ";
break;
case 11:
month_en = " November ";
month_ar = " نوفمبر ";
break;
case 12:
month_en = " December ";
month_ar = " ديسمبر ";
break;
}
const created_at_ar = created_at.replace(/\d/g, d => '٠١٢٣٤٥٦٧٨٩'[d]);
//Ready English format
const created_at_en = setCharAt(created_at, 4, month_en);
//Ready Arabic format
created_at_ar = setCharAt(created_at_ar, 4, month_ar);
//Link post image name with the complete require link
const image = postsData[i].image;
imageLink = imageLink.substr(0,imageLink.length) + image;
const post = {
id: postsData[i].id,
title: postsData[i].title,
description: filteredDescription,
type: postsData[i].type,
category_id: postsData[i].category_id,
image: imageLink,
created_at_ar: created_at_ar,
created_at_en: created_at_en,
likesNo: likesNo[i],
commentsNo: commentsNo[i],
}
//push posts data to one array
posts.push(post);
//collect posts id to send it back and get a new array of posts
postsIds.push(post.id);
}
if (fetchDataCounter == 0){
var newPostsState = posts;
var newPostsIdsState = postsIds;
}
else{
//merge old posts state array with new one
oldPostsState = action.posts;
var newPostsState = oldPostsState.concat(posts);
//merge old posts ids state array with new one
oldPostsIdsState = action.postsIds;
var newPostsIdsState = oldPostsIdsState.concat(postsIds);
}
fetchDataCounter ++;
return update(state, {
posts:{
$set: newPostsState
},
postsIds:{
$set: newPostsIdsState
},
postsFetched: {
$set: true
}
});
}
const ACTION_HANDLER = {
NEWS_FEED_POSTS:handleNewsFeedPosts
}
const initialState = {
posts:[],
postsFetched: false,
postsIds:{},
data: 'blablabla...'
}
Upvotes: 0
Views: 1651
Reputation: 690
<FlatList
style = {styles.myAddressList}
data = {useSelector((state) => state.address.address)}
renderItem = {renderItem}
keyExtractor = {item => item._id}
ListEmptyComponent = {EmptyList}
ItemSeparatorComponent={SeparatorWhite}
/>
Upvotes: 0
Reputation: 429
First of all, FlatList scrolls by itself, you don't need to wrap it in a ScrollView.
Also, I think the problem is here
renderItem={({postData}) => (<Text>{postData.title}</Text>)}
renderItem is a function which an object parameter with the following structure:
export interface ListRenderItemInfo<ItemT> {
item: ItemT;
index: number;
separators: {
highlight: () => void;
unhighlight: () => void;
updateProps: (select: "leading" | "trailing", newProps: any) => void;
};
}
You need to extract the item object in your renderItem function like this
renderItem={({item}) => (<Text>{item.title}</Text>)}
Then it'd work :)
Upvotes: 1