更新组件状态以使用 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}
    
    />