更新组件状态以使用 Redux 在 Flatlist 中查看数据
Update component state to view data in Flatlist with Redux
我正在使用 Redux 获取数据并将其添加到商店,添加后我尝试在平面列表中查看结果,但记录器中出现以下错误消息
我搜索了一段时间,发现我必须使用条件来防止 Flat List 在获取数据并添加到商店之前呈现,所以我尝试将我的数据列表分配给我的本地组件使用 componentWillReceiveProps 状态强制组件重新呈现并查看 Flat List 中的数据列表,但突然出现相同的错误,尽管我已经使用了使 Flat List 等待数据接收并保存到存储的条件。
数据如下所示
homePage.js 包含平面列表
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;
包含 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);
componentdidmount()在HomePage.js
中调用的Action Handler函数
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...'
}
首先,FlatList是自己滚动的,不需要用ScrollView包裹起来。
另外,我觉得问题出在这里
renderItem={({postData}) => (<Text>{postData.title}</Text>)}
renderItem 是一个具有以下结构的对象参数的函数:
export interface ListRenderItemInfo<ItemT> {
item: ItemT;
index: number;
separators: {
highlight: () => void;
unhighlight: () => void;
updateProps: (select: "leading" | "trailing", newProps: any) => void;
};
}
您需要像这样在 renderItem 函数中提取项目对象
renderItem={({item}) => (<Text>{item.title}</Text>)}
然后就可以了:)
<FlatList
style = {styles.myAddressList}
data = {useSelector((state) => state.address.address)}
renderItem = {renderItem}
keyExtractor = {item => item._id}
ListEmptyComponent = {EmptyList}
ItemSeparatorComponent={SeparatorWhite}
/>
我正在使用 Redux 获取数据并将其添加到商店,添加后我尝试在平面列表中查看结果,但记录器中出现以下错误消息
我搜索了一段时间,发现我必须使用条件来防止 Flat List 在获取数据并添加到商店之前呈现,所以我尝试将我的数据列表分配给我的本地组件使用 componentWillReceiveProps 状态强制组件重新呈现并查看 Flat List 中的数据列表,但突然出现相同的错误,尽管我已经使用了使 Flat List 等待数据接收并保存到存储的条件。
数据如下所示
homePage.js 包含平面列表
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;
包含 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);
componentdidmount()在HomePage.js
中调用的Action Handler函数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...'
}
首先,FlatList是自己滚动的,不需要用ScrollView包裹起来。
另外,我觉得问题出在这里
renderItem={({postData}) => (<Text>{postData.title}</Text>)}
renderItem 是一个具有以下结构的对象参数的函数:
export interface ListRenderItemInfo<ItemT> {
item: ItemT;
index: number;
separators: {
highlight: () => void;
unhighlight: () => void;
updateProps: (select: "leading" | "trailing", newProps: any) => void;
};
}
您需要像这样在 renderItem 函数中提取项目对象
renderItem={({item}) => (<Text>{item.title}</Text>)}
然后就可以了:)
<FlatList
style = {styles.myAddressList}
data = {useSelector((state) => state.address.address)}
renderItem = {renderItem}
keyExtractor = {item => item._id}
ListEmptyComponent = {EmptyList}
ItemSeparatorComponent={SeparatorWhite}
/>