【问题标题】:dataSource is updated but Listview is not refreshed in react-native after componentWillReceivePropsdataSource 已更新,但在 componentWillReceiveProps 之后未在 react-native 中刷新 Listview
【发布时间】:2016-08-19 21:33:51
【问题描述】:

我正在尝试在 componentWillReceiveProps 执行时刷新列表视图。获取后似乎 dataSource 已更新(我将 console.log(this.state.dataSource) 放入 render() 并根据端点的当前状态更改。)

但是,ListView 保持不变。我想知道为什么并对 dataSource 持怀疑态度。所以我最终制作了字符串对象以在渲染()中打印出数据源。 var str = JSON.stringify(this.state.dataSource._dataBlob.s1);

还有<View><Text>{str}</Text>

当 componentWillReceiveProps() 执行时,上述部分发生了变化。但是,列表视图保持不变。我不知道为什么会这样。

这是我的代码的 sn-p。

componentWillReceiveProps(){
    var query = ApiUrl.urlForWeekInfo(this.state.email);
    console.log(query);
    this._executeQuery(query,3);
  }


  constructor(props) {
    super(props);

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

      this.state = {
      isLoading: false,
      ...
      first_name: this.props.first_name,
      email: this.props.email,
      dataSource: dataSource.cloneWithRows(this.props.listings)      
    };
  }
..

_executeQuery(query,i) {

    this.setState({ isLoading: true });
    fetch(query)
      .then(response => response.json())
      .then(json => this._handleResponse(json.response,i))
      .catch(error =>
         this.setState({
          isLoading: false,
          message: 'Something bad happened ' + error
    }));
  }

  _handleResponse(response,i) {
    this.setState({ isLoading: false , message: '' });
    if (response.application_response_code.substr(0, 1) === '1') {
      if(i==1){
        this.props.navigator.push({
          title: 'Apply',
          component: Apply,
          passProps: {listings: response.listings, times: response.timetable, week_num: this.state.week_num}
        });
      } else if (i==3){

        var output = response.listings;
        this.setState({
          dataSource: this.state.dataSource.cloneWithRows(output)
        });

        console.log(response.listings);
        this.forceUpdate();

      }
    } else {
    }
  }

render() {

    console.log(this.state.dataSource._dataBlob.s1);

    var str = JSON.stringify(this.state.dataSource._dataBlob.s1);
    var listviewsource = this.state.dataSource;

    return (

    <View style={[this.border('red'), styles.container_top]}>
      <View style={[this.border('black'), styles.container_top_buttons]} >

        <ListView
          dataSource={listviewsource}
          renderRow={this.renderRow.bind(this)}/> 

      </View>      
      {spinner}
      <View>
      <Text>{str}</Text>
      </View>

    </View>




        );
        }}

请分享您可能有的任何想法或经验。


我最终找到了解决这个问题的方法:

var array = response.listings;
    var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
    //=> call another ds variable.

    this.setState({
      rawData: array,
      dataSource: ds.cloneWithRows(response.listings)
    });

【问题讨论】:

    标签: listview react-native


    【解决方案1】:

    没有直接的方法可以将行更新到您的 ListView。关于ListView.DataSource 的文档不多。就这样吧——

    如果你想从 ListView 中添加/追加/前置/更新/删除行,你只需更新数据源并在 setState 中调用 cloneWithRows()。

    例如。我想从 URL 获取数据。每次点击“加载更多”时,我都会将新行添加到我的数据源中。

    getInitialState: function(){
        return {
            rawData: [],
            dataSource: new ListView.DataSource({
              rowHasChanged: (row1, row2) => row1 !== row2
            }),
            loaded: false,
            page: 1,
        }
    },
    

    第一次,我在 ComponentDidMount() 中调用此函数,它使用初始数据填充我的 ListView,并且状态为“page”=1。

      reloadData: function(){
        this.setState({ loaded: false, rawData: [], page: 1 });
    
        API.getUpcomingMovies(this.state.page)
          .then((data) => {
              this.setState({
                rawData: this.state.rawData.concat(data),
                dataSource: this.state.dataSource.cloneWithRows(this.state.rawData.concat(data)),
                loaded: true,
              });
          });
      },
    

    每次我点击“加载更多”以从 API 获取 JSON 时,我都会调用以下函数。每次我点击“加载更多”时,“页面”都会增加。

    fetchData: function(){
    
        this.setState({ loaded: false, page: this.state.page+1 });
    
        API.getUpcomingMovies(this.state.page)
            .then((data) => {
                this.setState({
                  rawData: this.state.rawData.concat(data),
                  dataSource: this.state.dataSource.cloneWithRows(this.state.rawData.concat(data)),
                  loaded: true,
                });
            });
      },
    

    如您所见,我正在连接我的 rawData[](这是一个包含 JSON 对象的简单数组)。如果您想在 rawData 中添加新数据,可以执行以下操作-

    this.setState({
        rawData: data.concat(this.state.rawData)
    )}
    

    【讨论】:

    • 在我的情况下,我不必连接或前置,而是完全重新加载所有内容。即使我用 cloneWithRows 语句触及了 dataSource,它对我也不起作用。我尝试使用'new ListView',它开始工作了!你会建议这样做有什么消极方面吗?
    • @SungpahLee 真的没什么!你做的和我的sn-p基本一样。我在getInitialState() 中有new ListView,你在constructor() 中有相同的。因此,IMO 我认为这种方法没有任何不利之处。但是,欢迎其他意见。此外,您可以直接替换数据而不是连接。 Gist 比这些原始操作更重要。记住,如果你想重新渲染数据,你只需要通过调用cloneWithRows(newdata)来更新state.dataSource。
    猜你喜欢
    • 2016-03-09
    • 1970-01-01
    • 2018-09-25
    • 1970-01-01
    • 2021-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多