Often, you'll fetch your list data from some API endpoint. In this section, you'll learn about making API requests from React Native components. The good news is that the fetch() API is pollyfilled by React Native, so the networking code in your mobile applications should look and feel a lot like it does in your web applications.
To start things off, let's build a mock API for our list items using functions that return promises just like fetch() does:
import fetchMock from 'fetch-mock';
import querystring from 'querystring';
// A mock item list...
const items = new Array(100).fill(null).map((v, i) => `Item ${i}`);
// The same filter and sort functionality
// as the previous example, only it's part of the
// API now, instead of part of the React component.
const filterAndSort = (data, text, asc) =>
data
.filter(i => text.length === 0 || i.includes(text))
.sort(
asc
? (a, b) => (b > a ? -1 : a === b ? 0 : 1)
: (a, b) => (a > b ? -1 : a === b ? 0 : 1)
);
export const fetchItems = (filter, asc) =>
new Promise(resolve => {
resolve({
json: () =>
Promise.resolve({
items: filterAndSort(items, filter, asc)
})
});
});
With the mock API function in place, let's make some changes to the list container component. Instead of using local data sources, you can now use the fetchItems() function to load data from the API mock:
import React, { Component } from 'react';
import { fetchItems } from './api';
import List from './List';
const mapItems = items =>
items.map((value, i) => ({ key: i.toString(), value }));
class ListContainer extends Component {
// The "source" state is empty because we need
// to fetch the data from the API.
state = {
asc: true,
filter: '',
data: []
};
// When the component is first mounted, fetch the initial
// items from the API, then
componentDidMount() {
fetchItems(this.state.filter, this.state.asc)
.then(resp => resp.json())
.then(({ items }) => {
this.setState({ data: mapItems(items) });
});
}
render() {
return (
<List
data={this.state.data}
asc={this.state.asc}
onFilter={text => {
// Makes an API call when the filter changes...
fetchItems(text, this.state.asc)
.then(resp => resp.json())
.then(({ items }) =>
this.setState({
filter: text,
data: mapItems(items)
})
);
}}
onSort={() => {
// Makes an API call when the sort order changes...
fetchItems(this.state.filter, !this.state.asc)
.then(resp => resp.json())
.then(({ items }) =>
this.setState({
asc: !this.state.asc,
data: mapItems(items)
})
);
}}
/>
);
}
}
export default ListContainer;
Any action that modifies the state of the list needs to call fetchItems(), and set the appropriate state once the promise resolves.