2017-08-14 225 views
4

我正在使用mobX为我的反应原生项目。请考虑这家店类:React组件不响应mobx可观察数据

class Birds { 
    @observable listOne = []; 
    @observable fetchingListOne = false; 
    @observable fetchErrorOne = ''; 

    @action setListOne =() => { 
     this.fetchingListOne = true; 
     api.getList() 
      .then((data) => { 
       this.listOne.replace(data); 
       this.fetchingListOne = false; 
      }) 
      .catch((error) => { 
       this.fetchingListOne = false; 
       this.fetchErrorOne = error; 
      }); 
    }; 
} 

而且这个反应成分:

@inject('BirdStore') @observer 
export default class Flat extends React.Component { 
    componentDidMount() { 
     this.props.BirdStore.setListOne(); 
    } 

    _renderHeader =() => { 
     return <Text style={styles.listHeaderText}> 
      Hello {this.props.BirdStore.listOne.length} is {this.props.BirdStore.fetchingListOne.toString()} 
      </Text>; 
    }; 

    _renderItem = ({item}) => { 
     return <Text style={styles.item}>{item.name}</Text> 
    }; 

    _renderFooter =() => { 
     if (this.props.BirdStore.fetchingListOne) { 
      return <ActivityIndicator/> 
     } 
     else { 
      return null 
     } 
    }; 

    render() { 
     const dataSource = this.props.BirdStore.listOne.slice(); 

     return (
       <View style={styles.container}> 
        <Text>Fetching: {this.props.BirdStore.fetchingListOne.toString()}</Text> 
        <FlatList 
         style={styles.listContainer} 
         ListHeaderComponent={this._renderHeader} 
         data={dataSource} 
         renderItem={this._renderItem} 
         keyExtractor={(item, i) => item.id} 
         ListFooterComponent={this._renderFooter} 
        /> 
       </View> 
     ) 
    } 
} 

从上面看起来对我说:

  1. Flat组件坐骑,它调用该方法的店面setListOne()
  2. setListOne()fetchingListOne设置为true并进行api调用。
  3. 在组件侧,当fetchingListOne为真时,ActivityIndi​​cator显示器,以及在ListHeaderComponent它应该显示真实的。
  4. 在商店方面,成功/不成功的回应后,它将fetchingListOne设置为false。
  5. 最后上的元件侧,因为fetchingListOne被设置为假,ActivityIndi​​cator不应显示和在ListHeaderComponent它应该显示假。

但是,这不是发生了什么事情。在调用setListOne()方法时,在将fetchingListOne设置为true后,该组件不会对api调用后所做的更改作出反应。而ActivityIndi​​cator不断显示,并在ListHeaderComponent其显示为真。

我在这里做错了什么?你可以帮我吗。谢谢

更新

我已在FlatList前添加一个文本组件。在组件类的render方法中添加一个Text组件或控制台日志记录会使FlatList对这些更改做出反应。我不知道为什么会发生这种情况。

+0

你能尝试使用'mobx.useStrict()',看看是否能解决您的问题?这意味着使用getters和setter来获得可观察值,特别是'fetchingListOne' –

+0

@ChristopherChiche我试着将'mobx.useStrict(true)'放在** Birds **类所在的store.js中。但是那给了我一个错误:* ...如果这个改变是有意的,请把代码包装在一个'action'中。试图修改:[email protected]] *。所以我把'useStrict();'放在'@action setListOne'中。它不会抛出任何错误,但它有同样的问题; ** FlatList **组件不会像它们应该那样对这些更改做出反应。 –

回答

2

这里最可能遇到的问题是,虽然Flatobserver组件,但FlatList不是(它毕竟是内置组件)。在这个设置_renderFooter和其他部分是renderFlatList,但不是FlatList。因此,他们是不平坦的生命周期的一部分,但FlatList的,因此不被Mobx跟踪

有两种方法来解决这个问题,既很简单:

1)申报_renderItem作为观察员部分:

_renderItem = observer(({item}) => 
    <Text style={styles.item}>{item.name}</Text> 
); 

2)使用内联匿名Observer组件:

_renderItem = ({item}) => 
    <Observer>{ 
     () => <Text style={styles.item}>{item.name}</Text>} 
    </Observer> 
+0

是的,我认为这是问题所在,因为我在FlatList上面添加了一个** Text **组件,并且它对变化做出了反应,*此外,这使得整个FlatList完美工作*(更新代码请看看在类的渲染方法)。无论如何,第一个方法给出了一个错误,[TypeError:不能作为函数调用类]。第二种方法基本上做同样的事情;它在提取后会渲染所有列表。 –