首页 文章

React Native:导航器弹出窗口中的更新视图(ListView)

提问于
浏览
3

我对React Native很新,并且在理解整个生态系统方面遇到了一些问题 . 无论如何,我有一个ListView,用户可以导航到另一个View,以便添加一个新项目,该项目将被添加到列表中 . 当我退回(弹出)时,由于数据源是在getInitialState中分配的,因此列表不会更新 .

当我弹出时,如何强制View更新列表?这是通过在导航器的onDidFocus中处理路径来完成的,还是我可以添加到实际的ListView中?

提供了代码的缩小版本,它是Budget-component及其列表,当导航器中有pop-event时需要更新它 .

索引文件

var BudgetWatch_ReactNative = React.createClass({

   renderScene(route, navigator){
      if(route.name == 'Main'){
         return React.createElement(route.component, {navigator});
      }
      if(route.name == 'Budgets'){
        return React.createElement(route.component, {navigator, realm});
      }
   },

   onDidFocus(route){
      // Insert React Native magic?
   },
   render() {
      return (
         <Navigator
            ref={(nav) => { navigator = nav; }}
            style={{flex:1}}
            initialRoute={{ name: 'Main', component: Main}}
            renderScene={this.renderScene}
            onDidFocus={this.onDidFocus}
            navigationBar={
               <Navigator.NavigationBar
               routeMapper={NavigationBarRouteMapper(realm)}
               />
         }/>
      )
   }
});

经济成分

class Budgets extends React.Component{
   render(){
      return (
         <View>
            <BudgetList navigator = {this.props.navigator}/>
         </View>
      )
   }
}

var BudgetList = React.createClass({
   getInitialState: function() {
      var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
      return {
         dataSource: ds.cloneWithRows(this.props.realm.objects('Budget')),
      };
   },

   render: function() {
      return (
         <ListView
            dataSource={this.state.dataSource}
            renderRow={this._renderRow}
         />
      );
   }
};

希望这足以让您了解问题,谢谢!

编辑:尝试到达一个函数,该函数将使用onDidFocus为列表设置数据的新状态 . 但由于对该函数的调用是通过route.component.prototype.updateData(data),因此this.setState返回"Cannot read property 'enqueueSetState' of undefined"

2 回答

  • 0

    所以我发现这应该是在React Native中呈现ListView的一个错误,并且通过添加一些不那么漂亮的代码,我得到了它的工作 .

    我在我的索引文件中添加了一个方法onDidFocus,每次显示一个组件时都会调用它(这样当用户弹出到上一个视图时就可以使用它) . 当onDidFocus中的路由是Budget时,我再次返回该组件 . 我还将ListView中使用的数据移出到我的索引中,以便ListView将数据作为属性获取,并在更改时重新呈现:

    index.android.js

    var BudgetWatch_ReactNative = React.createClass({
    
       renderScene(route, navigator){
          if(route.name == 'Main'){
             return React.createElement(route.component, {navigator});
          }
          if(route.name == 'Budgets'){
              var data = realm.objects('Budget').sorted('name');
              return <Budgets navigator={navigator} realm={realm} data={data} />
          }
       },
    
       onDidFocus(route){
           if(route.name==='Budgets'){
               var data = realm.objects('Budget').sorted('name');
               return <Budgets navigator={navigator} realm={realm} data={data} />
           }
       },
       render() {
          return (
             <Navigator
                ref={(nav) => { navigator = nav; }}
                style={{flex:1}}
                initialRoute={{ name: 'Main', component: Main}}
                renderScene={this.renderScene}
                onDidFocus={this.onDidFocus}
                navigationBar={
                   <Navigator.NavigationBar
                   routeMapper={NavigationBarRouteMapper(realm)}
                   />
             }/>
          )
       }
    });
    

    接下来在BudgetComponent.js中,我只是将props中的数据设置为状态,并使用该状态数据将其作为道具发送到我的BudgetList组件(我还将其更改为类而不是组件,但这并不重要):

    var Budgets = React.createClass({
        getInitialState: function() {
            var propsdata = this.props.data;
            return {
                data: propsdata,
            };
         },
    
         render(){
           return (
             <View style={styles.container}>
               <BudgetList data={this.props.data} realm={this.props.realm} navigator = {this.props.navigator} />
             </View>
         )
      });
    

    现在这应该可以工作,但是由于这个bug,List中的DataSource无法正常工作,所以通过使用方法componentWillUpdate(在查看List时一直调用),我可以强制更新数据 . 但是,为了不陷入无限循环,我必须检查数据是否应该更新,否则它将无法更新数据:

    BudgetList.js

    var BudgetList = React.createClass({
       getInitialState: function() {
          var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
          var data = this.props.data;
          return {
             data: this.props.data,
             dataSource: ds.cloneWithRows(this.props.data),
          };
        },
    
        componentWillUpdate (nextProps) {
           if (this.state.dataSource._cachedRowCount !== this.props.data.length) {
              this.setState({
              data: this.props.data,
              dataSource: this.state.dataSource.cloneWithRows(this.props.data)
              })
           }
        },
    
        _renderRow: function(rowData: string, sectionID: number, rowID: number) {
           return(
              <View>
                 <Text>{rowData.name}</Text>
              </View>
           )
        }
    });
    
  • -1

    我使用 componentDidMount 解决了这个问题,每次出现Component时都会调用它 . 这个解决方案目前正在为我工作 .

    例如,

    var ListPage = React.createClass({
      getInitialState() {
        return {
          dataSource: ds.cloneWithRows( this._generateRows( this.props.list ) ),
          currentPosition: 'unknown'
        }
      },
    
      componentDidMount() {
        this._reloadListView();
      },
    
      _reloadListView() {
        this.setState({
          dataSource: ds.cloneWithRows( this.props.list ),
        });
      },
    
      _generateRows( list ) {
        rows = [];
        list.forEach( function( item, index ) {
          rows.push( item );
        });
        return rows
      },
    
      _renderRow( rowData ) {
        return (
          <Text>{ 'id: ' + rowData[ 'id' ] + ' ' + rowData[ 'info' ][ 'value' ][ 'name' ]}</Text>
        );
      },
    
      render() {
        return (
          <ListView
            dataSource = { this.state.dataSource }
            renderRow = { this._renderRow }
          />
        )
      },
    });
    
    module.exports = ListPage;
    

相关问题