无法让ListView重新渲染

时间:2015-12-31 13:06:51

标签: react-native

我试图强制ListView重新渲染,只修改已更改的行。 文档建议使用rowHasChanged函数。我不确定我是否正确使用它。 这里有经过修改的代码供参考,但对我来说并不适用:



'use strict'

import React from 'react-native';
import {
  ListView,
  View,
  TouchableOpacity,
  Component
}
from 'react-native';


export default class Follows extends Component {
  constructor() {
    super()
    this.state = {
      apiData: [],
      dataSource: new ListView.DataSource({
        rowHasChanged: (row1, row2) => row1.id !== row2.id || row1.following !== row2.following
      })
    };
  }

  _fetchData() {
    fetch(some_url)
      .then((response) => response.json())
      .then((responseData) => {
        this.state.apiData = responseData.data;
        this.setState({
          dataSource: this.state.dataSource.cloneWithRows(this.state.apiData),
        });
      })
      .catch((error) => {
        callOnFetchError(error, some_url);
      }).done();
  })
}

componentDidMount() {
  this._fetchData()
}

_follow(id, shouldFollow) {
  const refreshedData = this.state.apiData.map(user => {
    if (user.id === id)
      user.following = shouldFollow ? 1 : 0;
    return user;
  })
  this.setState({
    dataSource: this.state.dataSource.cloneWithRows(refreshedData),
  })
}

_renderRow() {
    return (
        <TouchableOpacity
            onPress = {this._follow.bind(this, 37, true}>
               
              /* some view */
        </TouchableOpacity>
	)
}

  render () {
    return (
      <View style={styles.container}>
        <ListView
          style={styles.listView}
          dataSource={ this.state.dataSource }
          renderRow={this._renderRow()}
        </ListView >
        < /View>
    )
  }
}
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:1)

尝试以下设置。我认为有两件事情使得功能对您不起作用:

1 - 您将dataSource称为this.state.dataSource.cloneWithRows的方式。相反,请尝试设置如下变量:

var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});

然后像这样使用它:

this.setState({
  dataSource: ds.cloneWithRows(responseData.data),
});

2 - 而不是:

this.state.apiData = responseData.data;

试试这个:

this.setState({
  apiData: responseData.data
})

总的来说,我已将原始代码更改为以下内容,我认为应该可以使用:

'use strict'

import React from 'react-native';
import {
  ListView,
  View,
  TouchableOpacity,
  Component
}
from 'react-native';

var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});

export default class Follows extends Component {
  constructor() {
    super()
    this.state = {
      apiData: [],
      dataSource: ds.cloneWithRows([])
    };
  }

  _fetchData() {
    fetch(some_url)
      .then((response) => response.json())
      .then((responseData) => {
        this.setState({
          apiData: responseData.data,
          dataSource: ds.cloneWithRows(responseData.data),
        });
      })
      .catch((error) => {
        callOnFetchError(error, some_url);
      }).done();
  })
}

componentDidMount() {
  this._fetchData()
}

_follow(id, shouldFollow) {
  const refreshedData = this.state.apiData.map(user => {
    if (user.id === id)
      user.following = shouldFollow ? 1 : 0;
    return user;
  })
  this.setState({
    dataSource: ds.cloneWithRows(refreshedData),
  })
}

_renderRow() {
    return (
        <TouchableOpacity
            onPress = {this._follow.bind(this, 37, true}>
               
              /* some view */
        </TouchableOpacity>
	)
}

  render () {
    return (
      <View style={styles.container}>
        <ListView
          style={styles.listView}
          dataSource={ this.state.dataSource }
          renderRow={this._renderRow()}
        </ListView >
        < /View>
    )
  }
}