[英]In react native this.setState() does not changes the state in fetch function
我一直在寻找解决方案的一天,我学到了很多,但没有弄清楚出了什么问题。 我在这里做什么:
这是 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 的回答。
我认为您误解了 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
来避免两次.then
调用。
你还有另一个问题。 您将列表视图链接到状态中的错误属性。 您在渲染中列出的视图代码应该是:
dataToDisplay = <ListView
dataSource={this.state.dataSource}
renderRow={(unit) => <UnitMenuCard name={unit.name} image={unit.picture} menu={unit.menu}/>}
/>
this.state.dataSource
是存储数据源对象的地方。
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}/>}
/>
数据源应该是您从 fetch 调用中获得的数据。 因此,dataSource 应该设置为等于 this.state.data。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.