javascript - 使用 Redux 更新组件状态以查看 Flatlist 中的数据
问题描述
我正在使用 Redux 获取数据并将其添加到存储中,添加后我尝试在平面列表中查看结果,但记录器中出现以下错误消息
我搜索了一段时间,发现我必须使用条件来防止平面列表在数据获取并添加到存储之前呈现,所以我尝试使用 componentWillReceiveProps 将我的数据列表分配给我的本地组件状态强制重新渲染和查看平面列表中的数据列表的组件,但突然出现相同的错误,尽管我已经使用了使平面列表等待数据接收并保存到存储的条件。
数据如下所示
包含平面列表的 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 的 Home 容器
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);
在 HomePage.js 中 componentdidmount() 调用的 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>)}
然后它会工作:)
推荐阅读
- c++ - 如何强制使用 SFML_DIR?
- css - 如何在 Chrome on Rails 中使用 FontAwesome 5?
- firebase - 如何在不登录的情况下将用户数据保存在数据库中?
- javascript - 下拉菜单自动更新按钮的 URL
- python - 如何获取bugzilla登录的api token
- python - Python(tkinter)获取检查了哪些检查按钮?
- java - Webdriver 在使用 selenium + cucumber + Page Factory Model 开发的框架上在功能文件执行时返回 null
- r - 在 RStudio 中打包 Metatrader
- reactjs - 对对象数组和 setState 进行排序导致无限循环
- python - 非常慢的 pyspark 过滤器