0

我希望有人可以帮助我,我一直在做一个多月的业余项目,但我无法弄清楚这一点。这是代码:

getNews() {
    var news_items = new Array();
    AsyncStorage.setItem('time', JSON.stringify({'last_cache': moment()}));
    var url = "http://api.podio.com/"
    fetch(url)
    .then(response => response.text())
    .then((responseText) => {
      const doc = new DOMParser().parseFromString(responseText, "text/xml");
      var items = doc.getElementsByTagName('item');
      for (var i = 0; i < items.length; i++) {
        var appType = new Object();
        appType.title = items[i].childNodes[1].childNodes[0].data;
        appType.link = items[i].childNodes[3].childNodes[0].data;
        news_items.push(appType);
      }
      var ds = this.state.dataSource.cloneWithRows(news_items);
      console.log("ds: ", ds)
      AsyncStorage.setItem('news_items', JSON.stringify(news_items));
      this.setState({
        'news': ds,
        'loaded': true
      })
      console.log("news: ", this.state.news)
    })
    .catch((error) => {
      console.log('Error fetching the feed: ', error);
    });
  }
}

render() {
  console.log("rendering....")
  console.log("loaded? ", this.state.loaded)
  return (
    <View style={styles.container}>
      <View style={styles.header}>
        <View style={styles.header_item}>
          <Text style={styles.header_text}>{this.state.title}</Text>
        </View>
        <View style={styles.header_item}>
          {  !this.state.loaded &&
            <ActivityIndicator />
          }
        </View>
      </View>
      <View style={styles.body}>
        <ScrollView ref="scrollView">
          {
            this.state.loaded && <ListView dataSource={this.state.dataSource} renderRow={this.renderNews} ></ListView>
          }
        </ScrollView>
      </View>
    </View>
  );
}

componentWillMount() {
  this.getNews();
}

renderNews() {
  console.log("loading....")
  return (
    <TouchableHighlight onPress={this.viewPage(news.link)} underlayColor={"#E8E8E8"} style={styles.button}>
    <View style={styles.news_item}>
    <Text style={styles.news_item_text}>{news.title}</Text>
      </View>
    </TouchableHighlight>
  );
}

如您所见,我在代码中有很多控制台日志。这是它告诉我的:

rendering....
loaded?  false
ds:  ListViewDataSource {_dataBlob: Object, _dirtyRows: Array[1],   _dirtySections: Array[1], _cachedRowCount: 142, rowIdentities: Array[1]…}
rendering....
loaded?  true
news:  ListViewDataSource {_dataBlob: Object, _dirtyRows: Array[1], _dirtySections: Array[1], _cachedRowCount: 142, rowIdentities: Array[1]…}

这是问题所在。在第一次渲染时,它显示“rendering....”,但加载为假,然后在此处设置 ds 变量:

var ds = this.state.dataSource.cloneWithRows(news_items); console.log("ds:", ds)

下次它再次渲染时显示“正在渲染......”,现在加载是真的。但是,从不调用 render 中的这一行:

this.state.loaded && <ListView dataSource={this.state.dataSource} renderRow={this.renderNews} ></ListView>

该行从不调用“this.renderNews”并显示其数据。

此外,我没有看到“正在加载......”的 console.log

值得一提的是 this.renderNews 是在构造函数中设置的。换句话说:this.renderNews = this.renderNews.bind(this)(edited)

4

2 回答 2

0

render挂载后失败,说明你setState打错了,让调用如下:

  this.setState({
    'news': ds || [],
    'loaded': true
  })

不是

  this.setState({
    'news': ds,
    'loaded': true
  })

这样,您就可以避免this.state.news不为空,(假设这news是一个数组。

于 2017-02-04T18:23:17.037 回答
0

不要在ListView. 总是渲染它,但最初数据源是空的。我的理解是第一次渲染构建组件树。然后随后的渲染实际上并没有重建树,它们只是更新现有组件上的数据。可以在组件上设置visible道具,重新渲染将正确显示/隐藏它们。

顺便说一句,你不需要ScrollView. ListView已经有滚动条了。嵌套滚动视图在移动设备上很糟糕。

于 2017-02-04T18:24:49.780 回答