setState со стрелкой не работает - PullRequest
0 голосов
/ 14 июля 2020

Не могли бы вы взглянуть на следующий код. Мне нужно получить какую-то ценность от другого класса. Это работает асинхронно, поэтому я предоставил функцию handleGameDeserialization. Функция получает правильное значение (как я тестировал с предупреждением), однако функция setState не влияет. Может быть, это проблема «этого контекста»?

export default class GameplayScreen extends React.Component {
  constructor(props) {
      super(props);
      this.fbGame = new FBGame();

      global.currentScreenIndex = 'Gameplay';

      this.state = {
        currentGame: 'N/A'
      }
      // this.handleGameDeserialization = this.handleGameDeserialization.bind(this);

      if (this.props.route.params != null) {
          this.gameKey = this.props.route.params.gameKey;
          this.game = this.fbGame.deserializeGame(this.gameKey, this.handleGameDeserialization);
      }
  }

  handleGameDeserialization = (game) => {
      //  alert('yeah'+game);   // here comes the expected output

      this.setState({
          currentGame: game
        });
  }

  render() {
      return (
        <View>
          <Text>{this.state.currentGame}</Text>
        </View>
        /*<Board game={this.state.game}/>*/
      )
  }
}

Я вызываю эту функцию при переходе к компоненту GameplayScreen. Как вы можете видеть выше, есть класс FBGame, который выполняет десериализацию (считайте игру из базы данных firebase)

export default class FBGame {
    ...
    deserializeGame(key, handleGameDeserialization) {
       var gameRef = firebase.database().ref("games/"+key).child("serialized");
       gameRef.on("value", snapshot => {
            //console.log('deserialized: ' + );
            handleGameDeserialization(snapshot.val().serialized);

       });
    }
    ...
}

редактировать:

Когда я использую componentDidMount, как показано ниже, он работает хорошо. Но это похоже на антипаттерн. Я до сих пор не понимаю, почему это не работает при вызове в конструкторе и как я должен это решить.

componentDidMount() {
      this.game = this.fbGame.deserializeGame(this.gameKey, this.handleGameDeserialization);
  }

1 Ответ

0 голосов
/ 15 июля 2020

Для таких вещей, как подписки, которые обновляют состояние и другие побочные эффекты, вы должны поместить logi c в componentDidMount(), который сработает сразу после установки компонента и не доставит вам никаких проблем, если вы обновить состояние внутри него. Вы не можете не делать того, что вызывает this.setState в конструкторе.

...