反应本机 ListView 数据源不更新

Posted

技术标签:

【中文标题】反应本机 ListView 数据源不更新【英文标题】:react native ListView datasource not updating 【发布时间】:2017-07-27 07:08:42 【问题描述】:

我正在尝试更新数据源,并且我检查了以下网址

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);

【问题讨论】:

您好样品可能会解决您的问题尝试一下hellokoding.com/todo-app-with-react-native-realm ***.com/questions/31738671/… 我已经尝试了这两个链接,请检查更新的代码并提出其中的任何错误。 【参考方案1】:

所以经过大量阅读和更改后,列表视图现在正在更新。 根据this发帖

将 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
               )


            

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

谢谢

【讨论】:

【参考方案2】:

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

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

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

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

之后只能这样设置:

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

【讨论】:

更新了我的代码。请检查 addToDo 方法将新对象添加到列表视图中。但是 changeisCompleted 方法什么也不做。

以上是关于反应本机 ListView 数据源不更新的主要内容,如果未能解决你的问题,请参考以下文章

更新道具时反应本机组件不透明度不更新

listView不显示,除非我滚动它

我在反应本机应用程序中使用 redux 来获取和显示数据,但它没有更新来自后端的数据更改

渲染后调用的函数反应原生

表单提交后的实时视图更新与本机反应

不变违规:不变违规:尝试从未标记为“本机”的节点获取本机标记 - 反应导航更新导致崩溃