我一直在寻找解决方案,我学到了很多,但没弄清楚出了什么问题。我在这做什么:
这是setState不会触发的地方。甚至不是渲染(它应该)。每个教程,每个论坛都以这种方式显示它(也是合乎逻辑的)。
以下是代码:
import Exponent from 'exponent';
import React from 'react';
import {
StyleSheet,
Text,
View,
ListView,
ActivityIndicator
} from 'react-native';
import { Button, Card } from 'react-native-material-design';
import {UnitMenuCard} from './unitmenucard.js';
class App extends React.Component {
constructor(props) {
super(props);
const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
this.state = {
loading: true,
dataSource: ds,
data: null
}
}
componentDidMount() {
//console.log('componentDidMount');
this.getData('https://dl.dropboxusercontent.com/u/76599014/testDATA.json');
}
getData(url) {
console.log('loading data');
return fetch(url).then(
(rawData) => {
console.log('parsing data');
//console.table(rawData);
return rawData.json();
}
).then(
(jsonData) =>
{
console.log('parsing to datablobs');
let datablobs = this.state.dataSource.cloneWithRows(jsonData);
console.log('datablobs: ' + datablobs);
return datablobs;
}
).then(
(datablobs) => {
console.log('setting state');
this.setState = ({
loading: false,
data: datablobs
});
console.log('the loading is ' + this.state.loading);
console.log('the data is ' + this.state.data);
}
).catch((errormsg) =>
{console.error('Loading error: ' + errormsg);}
);
}
render() {
console.log('loading is ' + this.state.loading);
var dataToDisplay = '';
if(this.state.loading) {
dataToDisplay = <ActivityIndicator animated={true} size='large' />
} else {
//let jdt = this.state.dataSource.cloneWithRows(this.state.data);
dataToDisplay = <ListView
dataSource={this.state.ds}
renderRow={(unit) => <UnitMenuCard name={unit.name} image={unit.picture} menu={unit.menu}/>}
/>
}
return (
<View style={styles.container}>
{dataToDisplay}
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
},
});
Exponent.registerRootComponent(App);
我错过了什么吗?谢谢你的回答强大Stack Overflow。
答案 0 :(得分:0)
我认为您误解了DatSource的工作原理。
getInitialState: function() {
var ds = new ListViewDataSource({rowHasChanged: this._rowHasChanged});
return {ds};
},
_onDataArrived(newData) {
this._data = this._data.concat(newData);
this.setState({
ds: this.state.ds.cloneWithRows(this._data)
});
}
这取自此处的文档:https://facebook.github.io/react-native/docs/listviewdatasource.html
了解如何在状态中克隆数据源对象。关键是你调用cloneWithRows
传递从API返回的数据(在你的情况下是jsonData
)。这将创建一个克隆的数据源,其中包含刚刚提取的数据。
在您的代码中,您只需创建数据源的克隆,但永远不会替换列表视图链接到的实际链接。你应该这样做:
.then(
(datablobs) => {
console.log('setting state');
this.setState = ({
loading: false,
dataSource: datablobs
});
console.log('the loading is ' + this.state.loading);
console.log('the data is ' + this.state.data);
}
您不需要state.data
,列表视图从数据源对象读取。您也可以通过简单地将所有内容整合在一起来避免两次.then
次呼叫。
您还有另一个问题。您将列表视图链接到状态中的错误属性。列表中的视图代码应该是:
dataToDisplay = <ListView
dataSource={this.state.dataSource}
renderRow={(unit) => <UnitMenuCard name={unit.name} image={unit.picture} menu={unit.menu}/>}
/>
this.state.dataSource
是存储数据源对象的地方。
答案 1 :(得分:0)
dataToDisplay = <ListView
dataSource={this.state.ds} // <- you set the dataSource to this.state.ds instead of this.state.data
renderRow={(unit) => <UnitMenuCard name={unit.name} image={unit.picture} menu={unit.menu}/>}
/>
数据源应该是您从提取调用中获得的数据。因此,dataSource应设置为等于this.state.data。