TypeError: undefined is not an object (evaluating '_this2.state.dataSource.cloneWithRows') when replacing ListView with FlatList

TypeError: undefined is not an object (evaluating '_this2.state.dataSource.cloneWithRows') when replacing ListView with FlatList

我正在将项目从 50~ 更新到 react-native 62+,并且 ListView 已从 react-native 中删除,因此我试图将此文件中的 ListView 更改为 FlatList。我不知道如何处理数据源来正确管理数据。有人可以帮我升级这个文件吗?

这是使用 ListView 的原始代码,我没有进行任何升级尝试,它给出了 "Invariant Error: ListView has been removed from React-Native":(我在下面尝试的代码)

'use strict';

import React, { Component } from 'react';
import {
  ListView,
  Platform,
  StyleSheet,
  Text,
  Image,
  View,
  TouchableOpacity,
  TouchableHighlight,
  TouchableNativeFeedback,
} from 'react-native';

import PoplarEnv from '../util/PoplarEnv';
import CommentCell from './CommentCell';
import {getCommentsOfObject} from '../api/CommentAPI';
import URLConf from '../api/URLConf';

const avatar_thumbnail = '?imageView2/1/w/48/h/48';

export default class CommentList extends Component{
  constructor(props) {
    super(props);
    this.state = {
      dataSource: new ListView.DataSource({
        rowHasChanged: (row1, row2) => row1 !== row2,
      }),
      loaded: false,
      replyModalVisible: false,
      commentsArray: [],
      commentCounter: this.props.commentCounter,
      commented: this.props.commented,
      limit: this.props.limit, //评论显示行数

      comment: null,
      commentBarVisible: false,
    };
  }

  componentDidMount() {
    this.fetchData();

  }

  /*
    被评论的feed类型
  */
  getCommentObjType(type) {
    var type_str = '';
    switch (type) {
      case PoplarEnv.COMMENT_OBJ_TYPE.POST:
        type_str = 'post';
        break;
      case PoplarEnv.COMMENT_OBJ_TYPE.PHOTO:
        type_str = 'photo';
        break;
      case PoplarEnv.COMMENT_OBJ_TYPE.ALBUM:
        type_str = 'album';
        break;
      case PoplarEnv.COMMENT_OBJ_TYPE.SPOST:
        type_str = 'spost';
        break;
      default:
        type_str = '';

    }
    return type_str;
  }

  fetchData() {
    var type_str = this.getCommentObjType(this.props.object_type);
    getCommentsOfObject(type_str, this.props.object_id,this.state.limit, (result, comments) => {
      this.setState({
        commentsArray: comments,
        dataSource: this.state.dataSource.cloneWithRows(comments),
        loaded: true,
      });
    });
  }

  renderLoadingView() {
    return (
      <View style={styles.container}>
        <Text>
          Loading...
        </Text>
      </View>

    );
  }


  setReplyModalVisible() {
    this.setState({replyModalVisible: true});
  }

  setReplyModalInVisible() {
    this.setState({replyModalVisible: false});
  }

  addNewComment(comment) {
    console.log('add new comment to comments list');
    console.log(comment);
    var commentsArray = this.state.commentsArray;
    commentsArray.push(comment);

    this.setState({
      dataSource: this.state.dataSource.cloneWithRows(commentsArray),
    });

  }

  componentWillReceiveProps(nextProps) {

    if(this.props.commentCounter == nextProps.commentCounter) return;

    if(nextProps.newComment != undefined && nextProps.newComment != null) {
        this.addNewComment(nextProps.newComment);
    }
  }

  render() {
    if(!this.state.loaded) {
      return this.renderLoadingView();
    }
    return this.renderCommentList(this.props.commentCounter);
  }


  showCommentBar() {
    this.setState({
      commentBarVisible: true,
    });
  }

  hideCommentBar() {
    this.setState({
      isComment: false,
      commentBarVisible: false,
    });
  }


  renderCommentList(commentCounter) {

    if(commentCounter > 0) {
      return (
        <TouchableOpacity style={styles.commentList} onPress={this.props.nav2FeedDetail}>
          <ListView
            dataSource={this.state.dataSource}
            renderRow={(comment)=>this.renderRow(comment, this.props.caller)}
          />
        </TouchableOpacity>
      );
    } else {
      return (<View/>);
    }

  }

  renderAuthorName(comment) {
    if(comment.comment_parent_author_name != undefined && comment.comment_parent_author_name != null) {
      return (<View style={{flex: 1, flexDirection: 'row'}}>
                <Text style={styles.username}>{comment.comment_author_name}</Text>
                <Text style={{fontSize: 14, color: '#9B9B9B', bottom: 1}}> Reply </Text>
                <Text style={styles.username}>{comment.comment_parent_author_name}</Text>
              </View>
            );
    } else {
      return (<Text style={styles.username}>{comment.comment_author_name}</Text>);
    }

  }

  renderRow(comment, caller) {
    if(comment == null || comment == undefined) {
      return (<View />);
    } else {
      if(caller == 'FeedCell') {
        return(
              <View style={styles.commentBox}>
                <Image style={styles.avatar} source={{uri:URLConf.IMG_BASE_URL+comment.comment_author_avatar+avatar_thumbnail}} />
                <View style={{flex:1}}>
                    {this.renderAuthorName(comment)}
                    <Text style={styles.comment}>{comment.comment_content}</Text>
                </View>
              </View>
        );
      } else if(caller == 'FeedDetail') {
        return(
          <CommentCell comment={comment} reply={this.props.reply}/>
        );
      }
    }
  }
};

var styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: 'row',
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: 'white',
  },
  commentList: {
    marginTop: -10,
    marginLeft:8,
    marginRight:8,
    paddingTop: 0,
  },
  commentBox: {
    flex: 1,
    flexDirection: 'row',
    //borderColor: 'black',
    //borderWidth: 1,
    padding: 10,
    paddingBottom: 4,
  },
  avatar: {
    borderRadius: 16,
    width: 32,
    height: 32,
    marginRight: 10,
  },
  username: {
    fontSize: 14,
    fontWeight: 'bold',
    color: 'black',
    // lineHeight: 13,
    marginBottom: 4,
  },
  commentTime: {

  },
  comment: {
    fontSize: 14,
    color: '#030303',
    lineHeight: 18,
  },
});

module.exports = CommentList;

这是我尝试升级它的代码,但我在第 78 行 "TypeError: undefined is not an object (evaluating '_this2.state.dataSource.cloneWithRows')" "dataSource: this.state.dataSource.cloneWithRows(comments),"

收到此错误
'use strict';

import React, { Component } from 'react';
import {
  FlatList,
  //ListView,
  Platform,
  StyleSheet,
  Text,
  Image,
  View,
  TouchableOpacity,
  TouchableHighlight,
  TouchableNativeFeedback,
} from 'react-native';

import PoplarEnv from '../util/PoplarEnv';
import CommentCell from './CommentCell';
import {getCommentsOfObject} from '../api/CommentAPI';
import URLConf from '../api/URLConf';

const avatar_thumbnail = '?imageView2/1/w/48/h/48';

export default class CommentList extends Component{
  constructor(props) {
    super(props);
    this.state = {
      // dataSource: new ListView.DataSource({
      //   rowHasChanged: (row1, row2) => row1 !== row2,
      // }),
      loaded: false,
      replyModalVisible: false,
      commentsArray: [],
      commentCounter: this.props.commentCounter,
      commented: this.props.commented,
      limit: this.props.limit, //评论显示行数

      comment: null,
      commentBarVisible: false,
    };
  }

  componentDidMount() {
    this.fetchData();

  }

  /*
    被评论的feed类型
  */
  getCommentObjType(type) {
    var type_str = '';
    switch (type) {
      case PoplarEnv.COMMENT_OBJ_TYPE.POST:
        type_str = 'post';
        break;
      case PoplarEnv.COMMENT_OBJ_TYPE.PHOTO:
        type_str = 'photo';
        break;
      case PoplarEnv.COMMENT_OBJ_TYPE.ALBUM:
        type_str = 'album';
        break;
      case PoplarEnv.COMMENT_OBJ_TYPE.SPOST:
        type_str = 'spost';
        break;
      default:
        type_str = '';

    }
    return type_str;
  }

  fetchData() {
    var type_str = this.getCommentObjType(this.props.object_type);
    getCommentsOfObject(type_str, this.props.object_id,this.state.limit, (result, comments) => {
      this.setState({
        commentsArray: comments,
        dataSource: this.state.dataSource.cloneWithRows(comments),
        loaded: true,
      });
    });
  }

  renderLoadingView() {
    return (
      <View style={styles.container}>
        <Text>
          Loading...
        </Text>
      </View>

    );
  }


  setReplyModalVisible() {
    this.setState({replyModalVisible: true});
  }

  setReplyModalInVisible() {
    this.setState({replyModalVisible: false});
  }

  addNewComment(comment) {
    console.log('add new comment to comments list');
    console.log(comment);
    var commentsArray = this.state.commentsArray;
    commentsArray.push(comment);

    this.setState({
      dataSource: this.state.dataSource.cloneWithRows(commentsArray),
    });

  }

  componentWillReceiveProps(nextProps) {

    if(this.props.commentCounter == nextProps.commentCounter) return;

    if(nextProps.newComment != undefined && nextProps.newComment != null) {
        this.addNewComment(nextProps.newComment);
    }
  }

  render() {
    if(!this.state.loaded) {
      return this.renderLoadingView();
    }
    return this.renderCommentList(this.props.commentCounter);
  }


  showCommentBar() {
    this.setState({
      commentBarVisible: true,
    });
  }

  hideCommentBar() {
    this.setState({
      isComment: false,
      commentBarVisible: false,
    });
  }


  renderCommentList(commentCounter) {

    if(commentCounter > 0) {
      return (
        <TouchableOpacity style={styles.commentList} onPress={this.props.nav2FeedDetail}>
          <FlatList
            data={this.state.dataSource}
            extraData={this.state}
            renderItem={(comment)=>this.renderRow(comment, this.props.caller)}
          />
          {/* <ListView
            dataSource={this.state.dataSource}
            renderRow={(comment)=>this.renderRow(comment, this.props.caller)}
          /> */}
        </TouchableOpacity>
      );
    } else {
      return (<View/>);
    }

  }

  renderAuthorName(comment) {
    if(comment.comment_parent_author_name != undefined && comment.comment_parent_author_name != null) {
      return (<View style={{flex: 1, flexDirection: 'row'}}>
                <Text style={styles.username}>{comment.comment_author_name}</Text>
                <Text style={{fontSize: 14, color: '#9B9B9B', bottom: 1}}> Reply </Text>
                <Text style={styles.username}>{comment.comment_parent_author_name}</Text>
              </View>
            );
    } else {
      return (<Text style={styles.username}>{comment.comment_author_name}</Text>);
    }

  }

  renderRow(comment, caller) {
    if(comment == null || comment == undefined) {
      return (<View />);
    } else {
      if(caller == 'FeedCell') {
        return(
              <View style={styles.commentBox}>
                <Image style={styles.avatar} source={{uri:URLConf.IMG_BASE_URL+comment.comment_author_avatar+avatar_thumbnail}} />
                <View style={{flex:1}}>
                    {this.renderAuthorName(comment)}
                    <Text style={styles.comment}>{comment.comment_content}</Text>
                </View>
              </View>
        );
      } else if(caller == 'FeedDetail') {
        return(
          <CommentCell comment={comment} reply={this.props.reply}/>
        );
      }
    }
  }
};

var styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: 'row',
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: 'white',
  },
  commentList: {
    marginTop: -10,
    marginLeft:8,
    marginRight:8,
    paddingTop: 0,
  },
  commentBox: {
    flex: 1,
    flexDirection: 'row',
    //borderColor: 'black',
    //borderWidth: 1,
    padding: 10,
    paddingBottom: 4,
  },
  avatar: {
    borderRadius: 16,
    width: 32,
    height: 32,
    marginRight: 10,
  },
  username: {
    fontSize: 14,
    fontWeight: 'bold',
    color: 'black',
    // lineHeight: 13,
    marginBottom: 4,
  },
  commentTime: {

  },
  comment: {
    fontSize: 14,
    color: '#030303',
    lineHeight: 18,
  },
});

module.exports = CommentList;

如果您需要更多代码,例如 CommentCell 或 FeedCell,请告诉我,我将编辑 post 以添加代码。有人可以帮我解决这个问题吗,我已经花了好几个小时了。

您必须将 ListView 完全更改为 Flatlist

所以首先从 react-native 导入 Flatlist :

import { FlatList } from "react-native";

然后将 ListView 更改为 Flatlist,如下所示:

renderCommentList(commentCounter) {
  if(commentCounter > 0) {
    return (
      <TouchableOpacity style={styles.commentList} onPress={this.props.nav2FeedDetail}>
        <FlatList
          data={this.state.dataSource}
          extraData={this.state}
          renderItem={({ item })=>this.renderRow(item, this.props.caller)}
        />
      </TouchableOpacity>
    );
  } else {
    return (<View/>);
  }
}

您可以找到更多文档here

更新

您的 dataSource 状态变量应该是这样的简单数组:

this.state = {
  dataSource: []
}

然后当您获取数据时,将您的数据附加到数据源状态变量中,如下所示:

this.setState({
  commentsArray: comments,
  dataSource: comments,
  loaded: true,
});

**注意:**您的 renderItems 方法应如下所示:

renderItem={({ comment })=>this.renderRow(comment, this.props.caller)}

comment 应该在 {} 大括号中。