Lazy list loading

In this section, we'll implement a different kind of list, one that scrolls infinitely. Sometimes, users don't actually know what they're looking for, so filtering or sorting isn't going to help. Think about the Facebook news feed you see when you log into your account; it's the main feature of the application and rarely are you looking for something specific. You'll need to see what's going on by scrolling through the list.

To do this using a ListView component, you need to be able to fetch more API data when the user scrolls to the end of the list. To get an idea of how this works, we need a lot of API data to work with. Generators are great at this! So let's modify the mock we created in the previous example so that it just keeps responding with new data:

import fetchMock from 'fetch-mock'; 
 
// Items...keep'em coming! 
function* genItems() { 
  let cnt = 0; 
 
  while (true) { 
    yield `Item ${cnt++}`; 
  } 
} 
 
const items = genItems(); 
 
// Grabs the next 20 items from the "items" 
// generator, and responds with the result. 
fetchMock.mock(//items.*/, () => { 
  const result = []; 
 
  for (let i = 0; i < 20; i++) { 
    result.push(items.next().value); 
  } 
 
  return ({ 
    items: result, 
  }); 
}); 

With this in place, you can now make an API request for new data every time the end of the list is reached. Well, eventually this will fail, but I'm just trying to show you in general terms the approach you can take to implement infinite scrolling in React Native. Here's what the ListContainer component looks like:

import React, { Component } from 'react'; 
import { ListView } from 'react-native'; 
 
import './mock'; 
import List from './List'; 
 
const rowHasChanged = (r1, r2) => r1 !== r2; 
const sectionHeaderHasChanged = rowHasChanged; 
 
class ListContainer extends Component { 
  constructor() { 
    super(); 
 
    this.state = { 
      data: [], 
      asc: true, 
      filter: '', 
      source: new ListView 
        .DataSource({ 
          rowHasChanged, 
          sectionHeaderHasChanged, 
        }) 
        .cloneWithRows([]), 
    }; 
 
    // This function is passed to the "onEndReached" 
    // property of the React Native "ListView" component. 
    // Instead of replacing the "source", it concatenates 
    // the new items with those that have already loaded. 
    this.fetchItems = () => 
      fetch('/items') 
        .then(resp => resp.json()) 
        .then(({ items }) => 
          this.setState({ 
            data: this.state.data.concat(items), 
            source: this.state.source.cloneWithRows( 
              this.state.data 
            ), 
          }) 
        ); 
  } 
 
  // Fetches the first batch of items once the 
  // component is mounted. 
  componentDidMount() { 
    this.fetchItems(); 
  } 
 
  render() { 
    return ( 
      <List 
        source={this.state.source} 
        fetchItems={this.fetchItems} 
      /> 
    ); 
  } 
} 
 
export default ListContainer; 

Each time fetchItems() is called, the response is concatenated with the data array. This becomes the new list data source, instead of replacing it as you did in earlier examples. Now let's take a look at the List component to see how you respond to the end of the list being reached:

import React, { PropTypes } from 'react'; 
import { Text, ListView } from 'react-native'; 
 
import styles from './styles'; 
 
// Renders a "<ListView>" component, and 
// calls "fetchItems()" and the user scrolls 
// to the end of the list. 
const List = ({ 
  source, 
  fetchItems, 
}) => ( 
  <ListView 
    enableEmptySections 
    dataSource={source} 
    renderRow={i => ( 
      <Text style={styles.item}>{i}</Text> 
    )} 
    onEndReached={fetchItems} 
  /> 
); 
 
List.propTypes = { 
  source: PropTypes.instanceOf(ListView.DataSource).isRequired, 
  fetchItems: PropTypes.func.isRequired, 
}; 
 
export default List; 

If you run this example, you'll see that, as you approach the bottom of the screen while scrolling, the list just keeps growing.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset