2015-06-15 32 views
17

So che c'è già una domanda simile ma non c'è codice condiviso lì.react-native this.setState non funziona

Sotto navbarChanged()> se condizione, sto facendo uno this.setState. Questo è di tipo HomeTab ma l'setState non sembra funzionare.

Eventuali indizi/indicazioni?

class HomeTab extends React.Component { 
    constructor() { 
    super() 

    this.setState({ 
     isNavBarHidden: false 
    }); 
    } 

    updatePosition(lastPosition) { 
    } 

    navbarChanged() { 
    console.log("received navbar changed event", AppStore.navbarVisible()); 

    if (AppStore.navbarVisible()) { 
     StatusBarIOS.setHidden(false) 
     this.setState({ isNavBarHidden: false}) 
     // this.state.isNavbarHidden is still true here 
     this.render(); 
    } 
    else { 
     StatusBarIOS.setHidden(true); 
     this.setState({ isNavBarHidden: true}); 
     this.render(); 
    } 
    } 

    componentDidMount() { 
    AppStore.addNavbarChangeListener(this.navbarChanged.bind(this)); 
    } 

    componentWillMount() { 
    StatusBarIOS.setHidden(false) 
    this.setState({ isNavBarHidden: false }); 
    } 
} 

Ed ecco il mio codice render():

render() { 
    return (
     <NavigatorIOS style={styles.container} 
      navigationBarHidden={this.state.isNavBarHidden} 
      ref="navigator" 
      initialRoute={{ 
       title: 'Foo', 
       component: HomeScreen, 
       passProps: { parent: this } 
      }} 
     /> 
    ) 
    } 

risposta

43

Non chiamare esplicitamente render. React eseguirà automaticamente un re-rendering quando lo stato o gli oggetti di scena cambiano, quindi non c'è bisogno di questo. Inoltre, dov'è il tuo attuale metodo render?

Per quanto riguarda il problema, il setState è asincrono e quindi tenta di lavorare con lo stato direttamente dopo una chiamata setState non funzionerà come l'aggiornamento non sarà necessariamente eseguito. Invece è possibile utilizzare il secondo argomento di setState che è un callback:

this.setState({ myVal: 'newVal'}, function() { 
    // do something with new state 
}); 

Questo sarà attivato dopo lo stato è stato impostato e dopo che il componente è stato ri-renderizzati.

+1

Grazie mille per la risposta. 'setState' è asincrono risponde a questa domanda. Ho aggiornato il mio codice con il mio metodo render(). Mi libererò di render(); quello che hai suggerito ha senso Sono ancora confuso però perché la mia barra di navigazione non viene mostrata (ma la barra del titolo è). – Abdo

+1

WOW grazie - non avevo idea nemmeno di leggere più e più volte i documenti che setState è asincrono - LONTANO DA ESSO molti tuts online dicono che l'interfaccia grafica renderà dopo aver chiamato questo - non immediatamente e la tua risposta mi ha aiutato in maniera massiccia. Grazie – landed

4

Invece di setState, utilizzare lo stato come membro di istanza della classe es6. la funzione setState può essere richiamata in un secondo momento per garantire i necessari re-rendering.

constructor() { 
    super() 

    this.state = { 
     isNavBarHidden: false 
    }; 
    } 
0

È inoltre possibile aggiornare lo stato delle eventHandlers e ascoltare componentWillReceiveProps per il codice che è necessario eseguire dopo i cambiamenti di stato.

componentWillReceiveProps(nextProps,nextState){ 
    if(this.state.myVar === nextState.myVar){ 
    return; 
    } 
    // TODO perform changes on state change 
} 

ritengo sia più ottimale rispetto alla soluzione proposta dal Colin Ramsay soprattutto come tutti sopra logica correrebbe prima render viene chiamato.

Problemi correlati