Home

Awesome

React Native RefreshableListView

A pull-to-refresh ListView which shows a loading spinner while your data reloads

Deprecated: now you can use the built-in RefreshControl instead.

Build Status

In action (from ReactNativeHackerNews):

React Native Hacker News

Usage

Note: these are the docs for the 2.x branch, currently in beta. If you are looking for the docs for a 1.x version, see the 1.x branch.

You can install the latest beta with npm install react-native-refreshable-listview@next

RefreshableListView

Replace a ListView with a RefreshableListView to add pulldown-to-refresh functionality. Accepts the same props as ListView, plus a few extras (see the props definitions below).

var React = require('react-native')
var {Text, View, ListView} = React
var RefreshableListView = require('react-native-refreshable-listview')

var ArticleStore = require('../stores/ArticleStore')
var StoreWatchMixin = require('./StoreWatchMixin')
var ArticleView = require('./ArticleView')

var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2}) // assumes immutable objects

var ArticlesScreen = React.createClass({
  mixins: [StoreWatchMixin],
  getInitialState() {
    return {dataSource: ds.cloneWithRows(ArticleStore.all())}
  },
  getStoreWatches() {
    this.watchStore(ArticleStore, () => {
      this.setState({dataSource: ds.cloneWithRows(ArticleStore.all())})
    })
  },
  reloadArticles() {
    // returns a Promise of reload completion
    // for a Promise-free version see ControlledRefreshableListView below
    return ArticleStore.reload()
  },
  renderArticle(article) {
    return <ArticleView article={article} />
  },
  render() {
    return (
      <RefreshableListView
        dataSource={this.state.dataSource}
        renderRow={this.renderArticle}
        loadData={this.reloadArticles}
        refreshDescription="Refreshing articles"
      />
    )
  }
})

Props

ControlledRefreshableListView

Low level component used by RefreshableListView. Use this directly if you want to manually control the refreshing status (rather than using a Promise).

This component is more suitable for use in a Redux-style connected component.

var React = require('react-native')
var {Text, View, ListView} = React
var {ControlledRefreshableListView} = require('react-native-refreshable-listview')

var ArticleView = require('./ArticleView')

var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2}) // assumes immutable objects

var ArticlesScreen = React.createClass({
  propTypes: {
    // eg. props mapped from store state
    articles: React.PropTypes.array.isRequired,
    isRefreshingArticles: React.PropTypes.bool.isRequired,
    // eg. a bound action creator
    refreshArticles: React.PropTypes.func.isRequired,
  },
  getInitialState() {
    return {dataSource: ds.cloneWithRows(this.props.articles)}
  },
  componentWillReceiveProps(nextProps) {
    if (this.props.articles !== nextProps.articles) {
      this.setState({dataSource: ds.cloneWithRows(nextProps.articles)})
    }
  },
  renderArticle(article) {
    return <ArticleView article={article} />
  },
  render() {
    return (
      <ControlledRefreshableListView
        dataSource={this.state.dataSource}
        renderRow={this.renderArticle}
        isRefreshing={this.props.isRefreshingArticles}
        onRefresh={this.props.refreshArticles}
        refreshDescription="Refreshing articles"
      />
    )
  }
})

Props

RefreshableListView.RefreshingIndicator

Component with activity indicator to be displayed in list header when refreshing. (also exposed as ControlledRefreshableListView.RefreshingIndicator)

Props

RefreshableListView.DataSource, ControlledRefreshableListView.DataSource

Aliases of ListView.DataSource, for convenience.

Howto

Customise the refresh indicator (spinner)

Your first option is to style the default RefreshingIndicator:

var indicatorStylesheet = StyleSheet.create({
  wrapper: {
    backgroundColor: 'red',
    height: 60,
    marginTop: 10,
  },
  content: {
    backgroundColor: 'blue',
    marginTop: 10,
    height: 60,
  },
})

<RefreshableListView
  refreshingIndicatorComponent={
    <RefreshableListView.RefreshingIndicator stylesheet={indicatorStylesheet} />
  }
/>

Alternatively, you can provide a custom RefreshingIndicator:

var MyRefreshingIndicator = React.createClass({
  render() {
    return (
      <View>
        <MySpinner />
        <Text>{this.props.description}</Text>
      </View>
    )
  },
})

<RefreshableListView refreshingIndicatorComponent={MyRefreshingIndicator} />
// or
<RefreshableListView refreshingIndicatorComponent={<MyRefreshingIndicator />} />

Changelog