web-dev-qa-db-fra.com

react-native this.setState ne fonctionne pas

Je sais qu'il y a déjà une question similaire mais il n'y a pas de code partagé là-dedans.

Sous navbarChanged()> si condition, je fais un this.setState. C'est de type HomeTab mais setState ne semble pas fonctionner.

Des indices/pointeurs?

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

Et voici mon code render ():

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

N'appelez pas explicitement render. React effectuera automatiquement un nouveau rendu lorsque l'état ou les accessoires changent, donc cela n'est pas nécessaire. De plus, où est votre véritable méthode render?

Quant à votre problème, setState est asynchrone et donc essayer de travailler avec l'état directement après un appel à setState ne fonctionnera pas car la mise à jour ne sera pas nécessairement exécutée. À la place, vous pouvez utiliser le deuxième argument pour setState qui est un rappel:

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

Cela sera déclenché après que l'état a été défini et après que le composant a été restitué.

59
Colin Ramsay

Au lieu de setState, utilisez state en tant que membre d'instance de la classe es6. la fonction setState peut être appelée plus tard pour garantir les rendus nécessaires.

  constructor() {
    super()

    this.state = {
      isNavBarHidden: false
    };
  }
4
RKichenama

Vous pouvez également mettre à jour l'état dans les gestionnaires d'événements et écouter componentWillReceiveProps pour le code que vous devez exécuter après le changement d'état.

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

Je pense que c'est plus optimal que la solution donnée par Colin Ramsay ci-dessus car toute la logique ci-dessus s'exécuterait avant que render soit appelé.

1
monish001