2017-08-14 2 views
4

J'utilise mobX pour mon projet natif réagissent. S'il vous plaît considérer cette classe de magasin:Réagir le composant ne réagit pas aux données observables 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; 
      }); 
    }; 
} 

Et ce composant réagit:

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

De-dessus il me semble que:

  1. Lorsque les supports composant Flat, il appelle la méthode du magasin setListOne().
  2. setListOne() définit fetchingListOne à true et effectue un appel api.
  3. Du côté des composants, lorsque le fetchingListOne est vrai, les ActivityIndicator affiche, et dans le ListHeaderComponent il devrait afficher vrai. Du côté du magasin, après une réponse réussie/non réussie, le paramètre fetchingListOne est défini sur false.
  4. Enfin du côté des composants, car fetchingListOne est réglé sur faux, ActivityIndicator ne devrait pas afficher et dans le ListHeaderComponent il devrait afficher de faux.

Cependant, ce n'est pas ce qui se passe. Ici, lorsque la méthode setListOne() est appelée, après avoir défini fetchingListOne sur true, le composant ne réagit pas aux modifications apportées après l'appel api. Et le ActivityIndicator continue à afficher et ListHeaderComponent son affichage vrai.

Qu'est-ce que je fais mal ici? Pourrais-tu m'aider s'il te plaît. Merci

Mise à jour

J'ai ajouté un composant texte avant la FlatList. L'ajout d'un composant Text ou d'une consignation de console dans la méthode de rendu de la classe de composant permet à FlatList de réagir aux modifications. Je ne sais pas pourquoi cela se passe bien.

+0

Pourriez-vous essayer d'utiliser 'mobx.useStrict()' pour voir si elle résout votre problème? Cela signifie utiliser des getters et setters pour vos valeurs observables, en particulier 'fetchingListOne' –

+0

@ChristopherChiche J'ai essayé de placer' mobx.useStrict (true) 'dans le store.js où la classe ** Birds ** est présente. Mais cela m'a donné une erreur: * ... S'il vous plaît envelopper le code dans une «action» si ce changement est prévu. J'ai essayé de modifier: [email protected]] *. J'ai donc placé 'useStrict();' dans '@action setListOne'. Il ne jette aucune erreur, mais il a le même problème; le composant ** FlatList ** ne réagit pas à ces changements comme ils devraient l'être. –

Répondre

2

Le problème que vous rencontrez probablement ici, c'est que bien que Flat soit un composant observer, FlatList ne l'est pas (c'est un composant intégré après tout). Dans cette configuration _renderFooter et les autres sont partie sont rendus par render de FlatList, mais pas de FlatList.Par conséquent, ils ne font pas partie du cycle de vie de plat, mais FlatList et en tant que tels ne sont pas suivis par MOBX

Il y a deux façons de résoudre ce problème, à la fois assez simple:

1) déclarer _renderItem en tant que composant d'observateur:

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

2) utiliser un composant anonyme en ligne Observer:

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

Oui, je pense que c'est le problème parce que j'ai ajouté un composant ** Text ** au-dessus de FlatList et il réagit aux changements, * aussi, cela fait fonctionner parfaitement FlatList * (mise à jour du code s'il vous plaît à la méthode de rendu de la classe). Quoi qu'il en soit, la première méthode donne une erreur, [TypeError: Impossible d'appeler une classe en tant que fonction]. Et la deuxième méthode fait essentiellement la même chose; il rend toute la liste après l'extraction. –