Estoy tratando de hacer un juego de TicTacToe para una aplicación de Android. El modo de juego de TicTacToe que pretendo hacer es Human-vs-Computer. Pero el problema es que el programa no actualizó el procedimiento de cambio (setState) en mi función switchPlayer ya que el jugador anterior y el jugador actual son los mismos después de hacer setState. La salida esperada de la función switchPlayer: Jugador anterior: 1, Jugador actual: -1 pero la salida real: Jugador anterior: 1, Jugador actual: 1.
También intenté usar el método de devolución de llamada como se sugirió/recomendó en otra pregunta de Stackoverflow, pero aún no funciona. ¿Lo estoy haciendo bien? Cualquier sugerencia será muy apreciada. Gracias de antemano.
Los códigos son los siguientes:
switchPlayer = (newPlayer) => { console.log("Previous player: "+this.state.currentPlayer); this.setState( {currentPlayer: newPlayer}, function () {console.log("Current player: "+this.state.currentPlayer); } ); }; onTilePress = (row, col, ValidMove) => { if (ValidMove == 1) { //If move is valid //Dont allow tiles to change var value = this.state.gameState[row][col]; if (value !== 0) { return;} //Identify and grab current player var PlayerNow = this.state.currentPlayer; console.log(row, col, PlayerNow); //Set the correct tile... var arr = this.state.gameState.slice(); arr[row][col] = PlayerNow; this.setState({gameState: arr}); //Switch to other player if (PlayerNow == 1) { //if player 1, then change to bot this.switchPlayer(-1); } else if (PlayerNow == -1) { this.switchPlayer(1); } console.log("New current player " + this.state.currentPlayer); //check winner var winner = this.getWinner(); //get the winner update if (winner == 1) { Alert.alert("Player 1 has won!"); this.initializeGame(); } else if (winner == -1){ Alert.alert("Bot has won!"); this.initializeGame(); } else if (this.checkTie() == 9){ //check if the match is a draw Alert.alert("It's a draw!"); this.initializeGame(); } //Alert.alert("It's Player "+takePlayer+"'s turn!"); this.BotMove(); } else { Alert.alert("Player 1, please make a move!"); } }Si su problema es que esperaba que la declaración de registro después de las llamadas a switchPlayer() ya incluyera los cambios de estado... Entonces debe poner todo después de su llamada a switchPlayer en una devolución de llamada que se ha propagado a través switchPlayer
switchPlayer = (newPlayer, cb) => { console.log("Previous player: "+this.state.currentPlayer); this.setState( {currentPlayer: newPlayer}, function () { console.log("Current player: "+this.state.currentPlayer); // Callers should put their code if (cb) { cb(); } } ); }; onTilePress = (row, col, ValidMove) => { // Switch to other player if (PlayerNow == 1) { //if player 1, then change to bot this.switchPlayer(-1, () => { // Here, you know the state has been updated }); } else if (PlayerNow == -1) { .... } // This code executes before the state is changed, you get the old state // All your code should really be in the callbacks to `switchPlayer` // or to any method that calls `setState` console.log("New current player " + this.state.currentPlayer); ... }Del documento React:
Debido a que this.props y this.state pueden actualizarse de forma asíncrona, no debe confiar en sus valores para calcular el siguiente estado.
Si desea manejar la actualización, puede probar componentDidUpdate
componentDidUpdate() se invoca inmediatamente después de que se produce la actualización. Este método no se llama para el renderizado inicial.
componentDidUpdate(prevProps, prevState) { if (this.state.currentUser !== prevState.currentUser) { console.log('previous user:', prevState.currentUser); console.log('current user:', this.state.currentUser); } } Si solo desea verificar que algo se ha actualizado (sin comparar con el valor anterior), puede usar render
render() { console.log('current user', this.state.currentUser); /* ... */ } Había un método más componentWillUpdate(nextProps, nextState) en el que podía comparar el estado actual y el siguiente, pero ahora está marcado como inseguro , por lo que no debe usarlo.
componentWillUpdate(nextProps, nextState) { if (this.state.currentUser !== nextState.currentUser) { console.log('current user:', this.state.currentUser); console.log('next user:', nextState.currentUser); } }https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate
Un consejo que puede resolver muchos problemas: no use function(){} como devolución de llamada, use funciones de flecha en su lugar () => {} , porque function(){} tiene su propio this y las funciones de flecha no lo tienen