davenull
davenull

Reputation: 23

How to force update of a listView in an _onPress method in React Native

I have a small API front end that works properly, except updating the ListView after an _onPress method is called to update the api data.

import React, {Component} from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  ListView,
  Image,
  RefreshControl,
  TouchableOpacity
} from 'react-native';
import Header from './Header';


export default class api extends Component {
  constructor(props) {
    super(props);

    this._onPress = this._onPress.bind(this);
    var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
    this.state = {
      refreshing: false,
      pageNumber: 0,
      flightsData: ds.cloneWithRows([]),
    };
  }


  fetchFlightsData() {
    /*removed for brevity*/
  }

  _onPress() {
    this.setState({refreshing: true});
    this.setState({pageNumber: this.state.pageNumber + 1});
    this.fetchFlightsData();
    this.setState({refreshing: false});
  };

  _onRefresh() {
    this.setState({pageNumber: 0});

    this.fetchFlightsData()
  }


  componentDidMount() {
    this.fetchFlightsData();
  }

  render() {

    return (

      <ListView
        renderHeader={() => <Header />}
        renderFooter={() => this.renderFooter() }
        dataSource={this.state.flightsData}
        renderRow={this.renderRow}
        style={styles.container}
        refreshControl={
          <RefreshControl
            refreshing={this.state.refreshing}
            onRefresh={this._onRefresh.bind(this)}
          />
        }
      />
    );
  }

  renderFooter() {

    return (

      <View style={styles.container}>
        <TouchableOpacity style={styles.button} onPress={() => this._onPress()}>
          <Text style={styles.text}>Load More</Text>
        </TouchableOpacity>
      </View>
    );
  }

  renderRow(rowData) {
    return (
/*removed for brevity*/
);
  }

}

const styles = StyleSheet.create({
  container: {
    backgroundColor: '#f2f2f2',
  },
  thumb: {
    backgroundColor: '#ffffff',
    marginBottom: 5,
    elevation: 1
  },
  img: {
    height: 300
  },
  txt: {
    margin: 10,
    fontSize: 16,
    textAlign: 'left'
  },
  button: {
    borderColor: '#8E8E8E',
    borderWidth: StyleSheet.hairlineWidth,
    paddingHorizontal: 20,
    paddingVertical: 10,
    borderRadius: 5,
  },
});


AppRegistry.registerComponent('api', () => api);

When the onPress method is called, it refreshes the data as expected, but does not update the ListView, that is until you press the button the second time, which it displays the new data from the first press.

The _onRefresh() method works exhibits similar behavior.

Upvotes: 0

Views: 375

Answers (1)

Matt Aft
Matt Aft

Reputation: 8936

setState does not change state immediately, you must use the optional second parameter if you want to do something after the state has been updated:

_onPress() {
  this.setState({ refreshing: true, pageNumber: this.state.pageNumber + 1 }, 
  () => this.fetchFlightsData());
  this.setState({refreshing: false}); //This part should probably go inside fetchFlightsData once you retrieve the data.
};

Upvotes: 1

Related Questions