繁体   English   中英

在 React Native 中 this.setState() 不会改变 fetch 函数中的状态

[英]In react native this.setState() does not changes the state in fetch function

我一直在寻找解决方案的一天,我学到了很多,但没有弄清楚出了什么问题。 我在这里做什么:

  1. 调用 App 构造函数; 初始化状态加载、数据源和数据
  2. 当组件挂载时,程序使用请求的 URL 调用 getData 函数
  3. getData 函数是一个异步获取函数
  4. 然后将数据转换为 JSON
  5. 然后将 JSON 克隆为 webview 的数据块
  6. 然后调用 setState 函数,更改加载和数据。

这是 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM