2016-08-16 66 views
0

我试图刷新listview时执行componentWillReceiveProps。看起来dataSource在获取后更新(我将console.log(this.state.dataSource)放在render()中并且它根据端点的当前状态而更改)。dataSource被更新,但listview没有刷新组件后的react-native nativeWillReceiveProps

但是,ListView保持不变。我想知道为什么,并怀疑dataSource。所以我最终使得string对象在render()中打印出dataSource。 var str = JSON.stringify(this.state.dataSource._dataBlob.s1);

而且<View><Text>{str}</Text>

componentWillReceiveProps()被执行时将上述部分的变化。但是,listview保持不变。我不知道为什么会发生这种情况。

这是我的代码的片段。

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) 
    }); 

回答

1

有更新的行到你的ListView没有直接的方法。在那里没有太多的文件ListView.DataSource。所以这里它去 -

如果你想添加/ append/prepend /更新/删除行从一个ListView,你只需要更新数据源并调用setState中的cloneWithRows()。

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

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

在第一次投票,我呼吁在ComponentDidMount此功能(),它填充的ListView我与初始数据和“网页” = 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时,我会调用以下函数。每次点击“加载更多”时,“页面”会增加。正如你所看到的,我将我的rawData [](这是一个包含JSON对象的简单数组)连接起来。如果你想新的数据预先考虑到您的RAWDATA,你可以不喜欢这个 -

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

就我而言,我没有来连接或预先准备,但完全重装所有的东西。即使我用cloneWithRows语句触及dataSource,它也不适用于我。我试图使用'新的ListView',它开始工作!你会建议采取这种方式的消极方面? –

+0

@SungpahLee真的没什么!你所做的与我的片段基本相同。我在'getInitialState()'中有'new ListView',并且在'constructor()'中有相同的。所以海事组织我认为这种方法没有任何不利之处。但是,其他意见是值得欢迎的。此外,您可以直接替换数据而不是串联。 Gist比这些原始的操作重要。记住,如果你想重新渲染数据,你只需要通过调用'cloneWithRows(newdata)'来更新state.dataSource。 – Mihir