【已开源】分享一个IT资讯软件,使用React Native写的
发布于 7 年前 作者 tomoya92 4308 次浏览 来自 分享

开源地址:https://github.com/tomoya92/ITNews-React-Native

介绍

平时看资讯用的app,里面很多功能都用不上,所以就想到了把它们集成到一块了,虽然网上也有很多这样的软件,但正好学一下rn,就自己实现了一个,实现思路是,有接口的,就调用接口,没有接口的,就直接抓取见面了用cheerio解析出数据

功能非常简单,列表(listview)+详情(webview)+分享功能

用到的组件:

  • StackNavigator
  • react-native-webview2
  • react-native-vector-icons
  • cheerio-without-node-native

截图:

image.png image.png Simulator Screen Shot 2017年8月7日 16.22.21.png

问题

现在发现了一个问题,ListView的加载更多问题,用的是onEndReached方法,在滚动到最后一行的时候,会触发的方法,在这里调用下一页,但在第一次加载更多的时候,会再一次加载第一页的内容,这样就导致了数据重复了,代码写法如下

export default class ItemList extends Component {
  static navigationOptions = ({navigation}) => ({
    title: `${navigation.state.params.name}`,
  });

  constructor(props) {
    super(props);

    this.state = ({
      refreshing: true,
      loadMore: false,
      name: this.props.name,
      pageNo: 1,
      dataSource: [],
    })
  }

  componentDidMount() {
    this._fetchData();
  }

  _fetchData() {
    fetch(url + 'api/v1/topics?page=' + this.state.pageNo)
      .then(response => response.json())
      .then(json => {
        this.setState({
          refreshing: false,
          loadMore: false,
          dataSource: this.state.pageNo === 1 ? json.data : this.state.dataSource.concat(json.data)
        })
      })
      .catch(error => console.info(error));
  }

  _onRefresh() {
    this.setState({
      pageNo: 1,
    });
    this._fetchData();
  }

  _onEndReached() {
    this.setState({
      loadMore: true,
      pageNo: this.state.pageNo + 1
    });
    this._fetchData();
  }

  _onPress(rowData) {
    const {navigate} = this.props.navigation;
    navigate('NewsDetail', {
      title: rowData.title,
      href: url + 'topic/' + rowData.id
    })
  }

  _renderRow(rowData) {
    return <TouchableHighlight
      underlayColor='#008b8b'
      onPress={() => this._onPress(rowData)}>
      <View style={styles.rowStyle}>
        <Image
          style={{width: 40, height: 40, borderRadius: 20}}
          source={{uri: rowData.author.avatar_url}}
        />
        <View style={{paddingLeft: 10, flexDirection: 'column', flex: 1}}>
          <Text style={{fontSize: 18,}}>{rowData.title}</Text>
          <View style={{flexDirection: 'row', justifyContent: 'space-between', alignItems: 'flex-end'}}>
            <Text style={styles.other}>{Moment(rowData.create_at).fromNow()}</Text>
            <Text style={[styles.other]}>{rowData.reply_count} 个回复</Text>
          </View>
        </View>
      </View>
    </TouchableHighlight>
  }

  render() {
    const FooterView = this.state.loadMore ?
      <View style={styles.footer}>
        <Text style={{fontSize: 18, color: '#777'}}>加载更多...</Text>
      </View> : null;
    return <ListView
      refreshControl={
        <RefreshControl
          refreshing={this.state.refreshing}
          onRefresh={this._onRefresh.bind(this)}
        />
      }
      style={[styles.listView]}
      dataSource={ds.cloneWithRows(this.state.dataSource)}
      enableEmptySections={true}
      renderRow={this._renderRow.bind(this)}
      onEndReachedThreshold={10}
      onEndReached={this._onEndReached.bind(this)}
      renderFooter={() => FooterView}
    />
  }
}

在这求大神帮忙看看,怎么能解决这个问题呢?

4 回复

这个问题有点难度

这有什么难的,如果正在加载更多就不再请求 来自 牛读 - 定制的技术类资讯聚合阅读器

因为this.setState({})方法是异步的,所以要用

this.setState({
	pageNo: 1
}, ()=>this._fetchData())

来进行调用,这样才能保证分页正确

回到顶部