2017-09-20 4 views
0

Le cas est que j'ai trois écrans, qui affichent les résultats obtenus à partir d'une API et permet à l'utilisateur d'envoyer des actions sur ces résultats. Ces actions déclenchent (devraient) des résultats dans les deux autres écrans. En d'autres termes, si l'utilisateur est sur un écran et effectue une action, les deux autres écrans doivent être mis à jour.Rendu conditionnel vs TabNavigator

Par exemple, les écrans A, B et C. je peux faire l'une des deux approches suivantes:

- Rendu conditionnel:

class MainScreen extends Component { 
    state: Object; 

    constructor(props) { 
     super(props); 

     this.state = { currentActiveScreen: 1 } 
    } 

    componentWillMount() 
    { 
     this.retrieveResultForScreenA(); 
     this.retrieveResultForScreenB(); 
     this.retrieveResultForScreenC(); 
    } 

    retrieveResultForScreenA() 
    { 
     // get results from API 
    } 

    retrieveResultForScreenB() 
    { 
     // get results from API 
    } 

    retrieveResultForScreenC() 
    { 
     // get results from API 
    } 

    ChangeScreen(screen_number) 
    { 
     this.setState({currentActiveScreen: screen_number}); 
    } 

    render() 
    { 
     if(this.state.currentActiveScreen === 1) 
     { 
      // render screen A results 
      // along with a tab bar to switch screens: 

      <View style={{flexDirection: "row"}}> 
       <TouchableOpacity onPress={()=>{ this.ChangeScreen.bind(this, 1) }}> 
        <Text>ScreenA</Text> 
       </TouchableOpacity> 
       <TouchableOpacity onPress={()=>{ this.ChangeScreen.bind(this, 2) }}> 
        <Text>ScreenB</Text> 
       </TouchableOpacity> 
       <TouchableOpacity onPress={()=>{ this.ChangeScreen.bind(this, 3) }}> 
        <Text>ScreenC</Text> 
       </TouchableOpacity> 
      </View> 

     } 

     if(this.state.currentActiveScreen === 2) 
     { 
      // render screen B results 
      // along with a tab bar to switch screens: 

      <View style={{flexDirection: "row"}}> 
       <TouchableOpacity onPress={()=>{ this.ChangeScreen.bind(this, 1) }}> 
        <Text>ScreenA</Text> 
       </TouchableOpacity> 
       <TouchableOpacity onPress={()=>{ this.ChangeScreen.bind(this, 2) }}> 
        <Text>ScreenB</Text> 
       </TouchableOpacity> 
       <TouchableOpacity onPress={()=>{ this.ChangeScreen.bind(this, 3) }}> 
        <Text>ScreenC</Text> 
       </TouchableOpacity> 
      </View> 
     } 

     if(this.state.currentActiveScreen === 3) 
     { 
      // render screen C results 
      // along with a tab bar to switch screens: 

      <View style={{flexDirection: "row"}}> 
       <TouchableOpacity onPress={()=>{ this.ChangeScreen.bind(this, 1) }}> 
        <Text>ScreenA</Text> 
       </TouchableOpacity> 
       <TouchableOpacity onPress={()=>{ this.ChangeScreen.bind(this, 2) }}> 
        <Text>ScreenA</Text> 
       </TouchableOpacity> 
       <TouchableOpacity onPress={()=>{ this.ChangeScreen.bind(this, 3) }}> 
        <Text>ScreenA</Text> 
       </TouchableOpacity> 
      </View>  
     } 
    } 
} 

- TabNavigator avec trois écrans:

class ScreenA extends Component { 

    static navigationOptions = ({ navigation }) => ({ title: 'ScreenA' }); 

    constructor(props) { 
     super(props); 
    } 

    componentWillMount() 
    { 
     this.retrieveResultForScreenA(); 
    } 

    retrieveResultForScreenA() 
    { 
     // get results from API 
    } 

    render() { 
     return (
      // render screen A results 
     ); 
    } 
} 

class ScreenB extends Component { 

    static navigationOptions = ({ navigation }) => ({ title: 'ScreenB' }); 

    constructor(props) { 
     super(props); 
    } 

    componentWillMount() 
    { 
     this.retrieveResultForScreenB(); 
    } 

    retrieveResultForScreenA() 
    { 
     // get results from API 
    } 

    render() { 
     return (
      // render screen B results 
     ); 
    } 
} 

class ScreenC extends Component { 

    static navigationOptions = ({ navigation }) => ({ title: 'ScreenC' }); 

    constructor(props) { 
     super(props); 
    } 

    componentWillMount() 
    { 
     this.retrieveResultForScreenC(); 
    } 

    retrieveResultForScreenA() 
    { 
     // get results from API 
    } 

    render() { 
     return (
      // render screen C results 
     ); 
    } 
} 

const MainScreen = TabNavigator({ 
    ScreenA: { screen: MyScreenA }, 
    ScreenB: { screen: MyScreenB }, 
    ScreenC: { screen: MyScreenC }, 
}); 

Problème avec la première approche est que:

  • si l'utilisateur passe écrans, l'application va chercher et utiliser le réseau, même si l'utilisateur n'a pas expédier toute action sur un écran

problème avec la deuxième approche est que:

  • les autres onglets ne seront pas mis à jour sur les actions distribuées (tabNavigator affiche une fois pour tous les écrans, et c'est tout)

Comment puis-je combiner b oth approches et ont un code propre, avec des écrans à jour?

+0

"si l'utilisateur change d'écran, l'application ira chercher et utilisera le réseau même si l'utilisateur n'a envoyé aucune action sur aucun écran"; Si le seul fetch se trouve sur componentWillMount du composant parent, alors ce n'est pas vrai .... – gravityplanx

+0

TabNavigator dans reac-navigation a un [paresseux] (https://reactnavigation.org/docs/navigators/tab# TabNavigatorConfig) prop – bennygenel

+0

Je ne suis pas sûr de ce que vous essayez d'atteindre ici, donc j'ai pensé que cela pourrait peut-être aider. paresseux prop rend les onglets quand ils sont commutés. Donc, si vous passez à TabA TabB TabB sera rendu à cette heure. – bennygenel

Répondre

1

En réponse à la discussion se déroulant dans les commentaires;

Il semble que ce que vous voulez vraiment, c'est une fonction gestionnaire qui peut déclencher des mises à jour sur des actions utilisateur spécifiques. Cela correspond, un peu, à votre modèle de conception "Conditional Render". Je vais donner un exemple, mais extrêmement simplifié;

class MainScreen extends Component { 
    state: Object; 

    constructor(props) { 
     super(props); 

     this.state = { currentActiveScreen: 1 } 
    } 

    componentWillMount() { 
     this.handleFetchRequest(); 
    } 

    getTabSelection() { 
     return (
      //some JSX with links that controls `state.currentActiveScreen` 
     ); 
    } 

    handleFetchRequest() { 
     this.retrieveResultForScreenA(); 
     this.retrieveResultForScreenB(); 
     this.retrieveResultForScreenC(); 
    } 

    getCurrentScreen() { 
     if(this.state.currentActiveScreen === 1) { 
      return <ScreenA onFetchRequest={this.handleFetchRequest}/>; 
     } 
     if(this.state.currentActiveScreen === 2) { 
      return <ScreenB onFetchRequest={this.handleFetchRequest}/>; 
     } 
     if(this.state.currentActiveScreen === 3) { 
      return <ScreenC onFetchRequest={this.handleFetchRequest}/>; 
     } 
    } 

    render() { 
     return <div> 
      {this.getTabSelection()} 
      {this.getCurrentScreen()} 
     </div>; 
    } 
} 

class ScreenA extends Component { 
    render() { 
     return <button onClick={this.props.onFetchRequest}/>; 
    } 
} 

Ainsi, dans l'exemple ci-dessus, le composant appellera handleFetchRequest une fois lorsque les premiers supports de composants, puis appellera plus lorsque l'utilisateur clique sur le bouton rendue dans ScreenA. Toute autre mise à jour ou nouveau rendu des composants ne provoquera pas de réexécution.

Vous pouvez continuer à étendre ce paramètre à d'autres actions de l'utilisateur qui doivent déclencher une reprise, telles que onFocus ou onBlur des zones de saisie.