反应本机 ListView 数据源不更新

react native ListView datasource not updating

我正在尝试更新数据源,我已经检查了以下 url

https://github.com/facebook/react-native/issues/4104 https://github.com/mobxjs/mobx/issues/569

我厌倦了创建一个新数组然后更新它,但我不确定如何更新数据源。

更改复选框后,我正在更新对象并将其分配给数据源,但复选框没有更新。

下面是我试过的代码。

构造函数

constructor() {
            super();
            const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});

            this.state = {
              modalVisible: false,
              todoText:'',
              todoListArray:[],
              dataSource: ds

            };

       }

列表视图

 <ListView
dataSource={this.state.dataSource}
        renderRow={this.generateRow.bind(this)}
        /> 

generateRow=(rowData, sectionID, rowID, highlightRow) => {

     return (
          <View style={styles.listItem}>
              <CheckBox 
                  label='' 
                  checked={rowData.isCompleted} 
                  onChange={() => {this.changeisCompleted(this,rowID)}}
              />
              <Text style={styles.listItemText}>{rowData.text}</Text>

          </View>

          );

    }

/*When Checkbox is clicked*/
    changeisCompleted=(rowData,rowId)=>{

       var newDs = [];
       newDs = this.state.todoListArray.slice();
       newDs[rowId].isCompleted =!newDs[rowId].isCompleted;
       alert(JSON.stringify(newDs));
       this.setState({
          dataSource: this.state.dataSource.cloneWithRows(newDs)
       })


    }

/*adding new item to listView*/
    addTodo = () => {
              var todoObj={
                "text":this.state.todoText,
                "isCompleted":false
              }
              this.state.todoListArray.push(todoObj);
              this.closeModal();
              this.setState({todoText: ''});
               this.setState({
                  dataSource: this.state.dataSource.cloneWithRows(this.state.todoListArray)
               })
            }

添加整个文件:

/**
     * Sample React Native App
     * https://github.com/facebook/react-native
     * @flow
     */

 import React, { Component } from 'react';
 import {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  ToolbarAndroid,
  Modal,
  Button,
  TextInput,
  Image,
  ListView,
  TouchableHighlight

} from 'react-native';

import CheckBox from 'react-native-checkbox';

{/*import AddToDoModal from './src/components/AddTodoModal.js';*/}


export default class FirstReactNativeApp extends Component {

  constructor() {
        super();
        const ds = new ListView.DataSource({rowHasChanged: (row1, row2) => row1 !== row2});

        this.state = {
          modalVisible: false,
          todoText:'',
          todoListArray:[],
          dataSource: ds,

        };

   }
componentDidMount = () => function() {

}

openModal = () => {
  this.setState({modalVisible: true});

}
closeModal = () => {
  this.setState({modalVisible: false});
}
setModalVisible=(visible) =>{
  this.setState({modalVisible: visible});
}
changeisCompleted=(rowData,rowId)=>{

   var newDs = [];
   newDs = this.state.todoListArray.slice();
   newDs[rowId].isCompleted =!newDs[rowId].isCompleted;
   newDs[rowId].text ="Changed";
   alert(JSON.stringify(newDs));
   //this.state.todoListArray=newDs;
   //alert("listArray=="+JSON.stringify(this.state.todoListArray))
   this.setState({
      todoListArray:newDs,
      dataSource: this.state.dataSource.cloneWithRows(newDs)
   })


}
addTodo = () => {
  var todoObj={
    "text":this.state.todoText,
    "isCompleted":false
  }
  this.state.todoListArray.push(todoObj);
  this.closeModal();
  this.setState({todoText: ''});
   this.setState({
      dataSource: this.state.dataSource.cloneWithRows(this.state.todoListArray)
   })
}
generateRow=(rowData, sectionID, rowID, highlightRow) => {


    return (
      <View style={styles.listItem}>
          <CheckBox 
              label='' 
              checked={rowData.isCompleted} 
              onChange={() => {this.changeisCompleted(this,rowID)}}
          />
          <Text style={styles.listItemText}>{rowData.text}</Text>

      </View>

      );

}

render() {
  return (
    <View>
          <ToolbarAndroid
          style={styles.toolbar}
          title="ToDo List"
          actions={[{title: 'Add', icon: require('./img/add.png'), show: 'always'}]}
          onActionSelected={this.openModal}
          />

          <ListView
          dataSource={this.state.dataSource}
          renderRow={this.generateRow.bind(this)}
          />



          <Modal
            animationType={"none"}
            transparent={false}
            visible={this.state.modalVisible}
            onRequestClose={() => {alert("Modal has been closed.")}} >

              <View style={styles.container}>
                 <View style={styles.modalContent}>

                        {/*this is icon button*/}
                      <TouchableHighlight style={{justifyContent:'flex-end',flexDirection:'row'}} onPress={this.closeModal}>
                          <Image
                              style={styles.closeButton}
                              source={require('./img/close.png')}
                          />
                      </TouchableHighlight>
                      <Text style={{textAlign:'center',marginBottom:30}}>Add New ToDo</Text>
                      <TextInput
                          style={{height: 40, borderColor: 'gray', borderWidth: 1,marginBottom:10}}
                          placeholder='Enter ToDo'
                          onChangeText={(todoText) => this.setState({todoText})}
                          value={this.state.todoText}
                      />
                     <Button 
                           onPress={()=> {this.addTodo()}}
                            title='Add ToDo'
                            color='#1e90ff'/>


                   </View>
              </View>
          </Modal>

  </View>
  );
}

}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#000000',
    opacity:0.8
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
  toolbar: {
    height:55,
    backgroundColor: '#1e90ff',
  },
  modal: {
    height:50,
    marginVertical:22,
  },
  modalContent: {
    backgroundColor: '#ffffff',
    height:300,
    width:300,
    borderRadius:3,
    paddingVertical:10,
    paddingHorizontal:20,

  },
  closeButton: {
    height:30,
    width:30,
  },
  listItem: {
    backgroundColor: '#ffffff',
    paddingLeft:10,
    height:50,
    borderBottomWidth:1,
    borderColor: '#000000',
    flex:1,
    flexDirection:'row',
    alignItems:'center',
  },
  listItemText: {

  fontSize:20,

  }
});

AppRegistry.registerComponent('FirstReactNativeApp', () => FirstReactNativeApp);

你有两个问题。首先,您将数据源设置为克隆的结果。只需使用 {this.state.dataSource}:

dataSource={this.state.dataSource.cloneWithRows(this.state.todoListArray)}

因为您正在设置 DS 结果而不是链接数据源。此外,您不需要状态中的双重数据(数组和数据源)。

第二个也是最重要的一点,您实际上并没有设置状态。只有在构造函数中你可以这样设置它:this.state。

之后就只能这样设置了:

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

因此,经过大量阅读和更改后,列表视图现在正在更新。 根据thispost

将 ds 声明更改为:

this.ds = new ListView.DataSource({rowHasChanged: (row1, row2) => row1 !== row2});

所以改变了我的 changeisComplete 方法

changeisCompleted=(rowData,rowId)=>{

           var newDs = [];
           newDs = this.state.todoListArray.slice();
           newDs[rowId].isCompleted =!newDs[rowId].isCompleted;


           this.setState({
                  dataSource: this.ds.cloneWithRows(this.state.todoListArray),
                  todoListArray:newDs
               })


            }

我不确定这是否是正确的方法,但无论如何它有效,现在复选框正在改变

谢谢