反应本机 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
})
}
我不确定这是否是正确的方法,但无论如何它有效,现在复选框正在改变
谢谢
我正在尝试更新数据源,我已经检查了以下 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
})
}
我不确定这是否是正确的方法,但无论如何它有效,现在复选框正在改变
谢谢