React-Native 更新列表视图数据源
React-Native Updating List View DataSource
我有一个 iOS 应用程序,我正在用 react-native 制作。游戏 class 包含一个 ListView 组件。我在构造函数中设置状态并包含一个 dataSource
。我现在有一个硬编码的数据数组,我存储在不同的状态 属性 (this.state.ds
)。然后在 componentDidMount
中,我使用 cloneWithRows
方法将我的 this.state.ds
克隆为视图的数据源。就 ListViews 而言,这是非常标准的,并且运行良好。这是代码:
/**
* Sample React Native App
* https://github.com/facebook/react-native
*/
'use strict';
var React = require("react-native");
var { StyleSheet, Text, View, ListView, TouchableHighlight } = React;
class Games extends React.Component {
constructor(props) {
super(props);
var ds = new ListView.DataSource({
rowHasChanged: (r1, r2) => r1 != r2
});
this.state = {
ds: [
{ AwayTeam: "TeamA", HomeTeam: "TeamB", Selection: "AwayTeam" },
{ AwayTeam: "TeamC", HomeTeam: "TeamD", Selection: "HomeTeam" }
],
dataSource: ds
};
}
componentDidMount() {
this.setState({
dataSource: this.state.dataSource.cloneWithRows(this.state.ds)
});
}
pressRow(rowData) {
var newDs = [];
newDs = this.state.ds;
newDs[0].Selection = newDs[0] == "AwayTeam" ? "HomeTeam" : "AwayTeam";
this.setState({
dataSource: this.state.dataSource.cloneWithRows(newDs)
});
}
renderRow(rowData) {
return (
<TouchableHighlight
onPress={() => this.pressRow(rowData)}
underlayColor="#ddd"
>
<View style={styles.row}>
<Text style={{ fontSize: 18 }}>
{rowData.AwayTeam} @ {rowData.HomeTeam}{" "}
</Text>
<View style={{ flex: 1 }}>
<Text style={styles.selectionText}>
{rowData[rowData.Selection]}
</Text>
</View>
</View>
</TouchableHighlight>
);
}
render() {
return (
<ListView
dataSource={this.state.dataSource}
renderRow={this.renderRow.bind(this)}
/>
);
}
}
var styles = StyleSheet.create({
row: {
flex: 1,
flexDirection: "row",
padding: 18,
borderBottomWidth: 1,
borderColor: "#d7d7d7"
},
selectionText: {
fontSize: 15,
paddingTop: 3,
color: "#b5b5b5",
textAlign: "right"
}
});
module.exports = Games
我遇到的问题来自 pressRow
方法。当用户按下该行时,我希望更改选择并让它在设备上呈现更改。通过一些调试,我注意到即使我正在更改 newDs
数组中对象的 Selection
属性,属性 中的对象也会发生相同的 属性 更改12=] 并类似地更改 this.state.dataSource._dataBlob.s1
中的对象。通过进一步调试,我发现由于其他数组发生了变化,ListView 的 DataSource 对象无法识别该变化,因为当我设置状态并调用 rowHasChanged
时,它正在克隆的数组与数组 this.state.dataSource._dataBlob.s1
所以它看起来不像是变化,也不会重新渲染。
有什么想法吗?
试试这个:
pressRow(rowData){
var newDs = [];
newDs = this.state.ds.slice();
newDs[0].Selection = newDs[0] == "AwayTeam" ? "HomeTeam" : "AwayTeam";
this.setState({
dataSource: this.state.dataSource.cloneWithRows(newDs)
})
}
这应该制作数组的副本,然后可以独立于 this.state.ds
中的原始数组对其进行修改。
如果有人像我一样遇到这个问题,这里是完整的解决方案。
基本上,ListView 组件似乎存在错误,您需要重建数据源中更改的每个项目,以便 ListView 重绘它。
首先,创建数据源和数组副本并将它们保存到状态。在我的例子中,foods
是数组。
constructor(props){
super(props);
var ds = new ListView.DataSource({
rowHasChanged: (row1, row2) => row1 !== row2,
});
this.state = {
dataSource: ds.cloneWithRows(foods),
db: foods,
};
}
当您想更改数据源中的某些内容时,复制您保存到状态的数组,重建包含更改的项目,然后将包含更改的新数组保存回状态(数据库和数据源)。
onCollapse(rowID: number) {
console.log("rowID", rowID);
var newArray = this.state.db.slice();
newArray[rowID] = {
key: newArray[rowID].key,
details: newArray[rowID].details,
isCollapsed: newArray[rowID].isCollapsed == false ? true : false,
};
this.setState({
dataSource: this.state.dataSource.cloneWithRows(newArray),
db: newArray,
});
}
react 足够智能,可以检测数据源的变化以及是否应该重新呈现列表。如果要更新 listView,请创建新对象而不是更新现有对象的属性。
代码看起来像这样:
let newArray = this._rows.slice();
newArray[rowID] = {
...this._rows[rowID],
Selection: !this._rows[rowID].Selection,
};
this._rows = newArray;
let newDataSource = this.ds.cloneWithRows(newArray);
this.setState({
dataSource: newDataSource
});
您可以阅读更多类似内容issue on Github
我有一个 iOS 应用程序,我正在用 react-native 制作。游戏 class 包含一个 ListView 组件。我在构造函数中设置状态并包含一个 dataSource
。我现在有一个硬编码的数据数组,我存储在不同的状态 属性 (this.state.ds
)。然后在 componentDidMount
中,我使用 cloneWithRows
方法将我的 this.state.ds
克隆为视图的数据源。就 ListViews 而言,这是非常标准的,并且运行良好。这是代码:
/**
* Sample React Native App
* https://github.com/facebook/react-native
*/
'use strict';
var React = require("react-native");
var { StyleSheet, Text, View, ListView, TouchableHighlight } = React;
class Games extends React.Component {
constructor(props) {
super(props);
var ds = new ListView.DataSource({
rowHasChanged: (r1, r2) => r1 != r2
});
this.state = {
ds: [
{ AwayTeam: "TeamA", HomeTeam: "TeamB", Selection: "AwayTeam" },
{ AwayTeam: "TeamC", HomeTeam: "TeamD", Selection: "HomeTeam" }
],
dataSource: ds
};
}
componentDidMount() {
this.setState({
dataSource: this.state.dataSource.cloneWithRows(this.state.ds)
});
}
pressRow(rowData) {
var newDs = [];
newDs = this.state.ds;
newDs[0].Selection = newDs[0] == "AwayTeam" ? "HomeTeam" : "AwayTeam";
this.setState({
dataSource: this.state.dataSource.cloneWithRows(newDs)
});
}
renderRow(rowData) {
return (
<TouchableHighlight
onPress={() => this.pressRow(rowData)}
underlayColor="#ddd"
>
<View style={styles.row}>
<Text style={{ fontSize: 18 }}>
{rowData.AwayTeam} @ {rowData.HomeTeam}{" "}
</Text>
<View style={{ flex: 1 }}>
<Text style={styles.selectionText}>
{rowData[rowData.Selection]}
</Text>
</View>
</View>
</TouchableHighlight>
);
}
render() {
return (
<ListView
dataSource={this.state.dataSource}
renderRow={this.renderRow.bind(this)}
/>
);
}
}
var styles = StyleSheet.create({
row: {
flex: 1,
flexDirection: "row",
padding: 18,
borderBottomWidth: 1,
borderColor: "#d7d7d7"
},
selectionText: {
fontSize: 15,
paddingTop: 3,
color: "#b5b5b5",
textAlign: "right"
}
});
module.exports = Games
我遇到的问题来自 pressRow
方法。当用户按下该行时,我希望更改选择并让它在设备上呈现更改。通过一些调试,我注意到即使我正在更改 newDs
数组中对象的 Selection
属性,属性 中的对象也会发生相同的 属性 更改12=] 并类似地更改 this.state.dataSource._dataBlob.s1
中的对象。通过进一步调试,我发现由于其他数组发生了变化,ListView 的 DataSource 对象无法识别该变化,因为当我设置状态并调用 rowHasChanged
时,它正在克隆的数组与数组 this.state.dataSource._dataBlob.s1
所以它看起来不像是变化,也不会重新渲染。
有什么想法吗?
试试这个:
pressRow(rowData){
var newDs = [];
newDs = this.state.ds.slice();
newDs[0].Selection = newDs[0] == "AwayTeam" ? "HomeTeam" : "AwayTeam";
this.setState({
dataSource: this.state.dataSource.cloneWithRows(newDs)
})
}
这应该制作数组的副本,然后可以独立于 this.state.ds
中的原始数组对其进行修改。
如果有人像我一样遇到这个问题,这里是完整的解决方案。
基本上,ListView 组件似乎存在错误,您需要重建数据源中更改的每个项目,以便 ListView 重绘它。
首先,创建数据源和数组副本并将它们保存到状态。在我的例子中,foods
是数组。
constructor(props){
super(props);
var ds = new ListView.DataSource({
rowHasChanged: (row1, row2) => row1 !== row2,
});
this.state = {
dataSource: ds.cloneWithRows(foods),
db: foods,
};
}
当您想更改数据源中的某些内容时,复制您保存到状态的数组,重建包含更改的项目,然后将包含更改的新数组保存回状态(数据库和数据源)。
onCollapse(rowID: number) {
console.log("rowID", rowID);
var newArray = this.state.db.slice();
newArray[rowID] = {
key: newArray[rowID].key,
details: newArray[rowID].details,
isCollapsed: newArray[rowID].isCollapsed == false ? true : false,
};
this.setState({
dataSource: this.state.dataSource.cloneWithRows(newArray),
db: newArray,
});
}
react 足够智能,可以检测数据源的变化以及是否应该重新呈现列表。如果要更新 listView,请创建新对象而不是更新现有对象的属性。 代码看起来像这样:
let newArray = this._rows.slice();
newArray[rowID] = {
...this._rows[rowID],
Selection: !this._rows[rowID].Selection,
};
this._rows = newArray;
let newDataSource = this.ds.cloneWithRows(newArray);
this.setState({
dataSource: newDataSource
});
您可以阅读更多类似内容issue on Github