Попытка изменить текст в зависимости от того, окончена игра или нет, react.js

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

Вот мой код: (Я пробовал несколько решений, но ни одно из них не сработало, я понятия не имею, что вызывает эту проблему, и поэтому я помещаю весь код)

function Square(props) {
  return (
    <button className = "square" onClick = {props.onClick}>
      {props.value}
    </button>
  );
}

function calculateWinner(squares) {
  const lines = [
    [0, 1, 2],
    [3, 4, 5],
    [6, 7, 8],
    [0, 3, 6],
    [1, 4, 7],
    [2, 5, 8],
    [0, 4, 8],
    [2, 4, 6],
  ];
  for (let i = 0; i < lines.length; i++) {
    const [a, b, c] = lines[i];
    if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
      return squares[a];
    }
  }
  return null;

class Board extends React.Component {
  renderSquare(i) {
    return <Square value = {this.props.squares[i]} 
    onClick = {()=>{this.props.onClick(i)}}/>;
  }
  
  render() {
    return (
      <div>
        <div className = "board-row">
          {this.renderSquare(0)}
          {this.renderSquare(1)}
          {this.renderSquare(2)}
        </div>
        <div className = "board-row">
          {this.renderSquare(3)}
          {this.renderSquare(4)}
          {this.renderSquare(5)}
        </div>
        <div className = "board-row">
          {this.renderSquare(6)}
            {this.renderSquare(7)}
            {this.renderSquare(8)}
          </div>
        </div>
    );
  }
}
  
class Game extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      history: [{
        squares: Array(9).fill(null)
      }],
      stepNumber: 0,
      xIsNext: true,
      winner: null
    }
  };

  handleClick(i) {
    const history = this.state.history.slice(0, this.state.stepNumber + 1);
    const current = history[history.length - 1];
    const squares = current.squares.slice();
    if (calculateWinner(squares) || squares[i]) {
      return;
    }
    squares[i] = this.state.xIsNext ? 'X' : 'O';
    this.setState({
      history: history.concat([{
        squares: squares,
      }]),
      stepNumber: history.length,
      xIsNext: !this.state.xIsNext,
    });
  }

  jumpTo(step) {
    this.setState({
      stepNumber: step,
      xIsNext: (step % 2) === 0,
    });
  }
  
  checkForWinner(squares,winr) {
    if (winr === null)
      this.setState({
        winner: calculateWinner(squares)
      })
  }
  
  render() {
    const history = this.state.history;
    const current = history[this.state.stepNumber];
    const winner = this.state.winner

    const moves = history.map((_, move) => {
      const desc = move ?
        'Go to move #' + move :
        'Go to game start';
      return (
        <li key = {move}>
          <button onClick = {() => this.jumpTo(move)}>{desc}</button>
        </li>
      );
    });

    return (
      <div className = "game">
        <div className = "game-board">
          <Board
            squares = {current.squares}
            onClick = {i => {
              if (!winner) {
                this.handleClick(i)
              }
              this.checkForWinner(current.squares, winner)
            }}
            
          />
        </div>
        <div className = "game-info">
          <div>{(winner) ? 'Winner: ' + winner : 'Next player: ' + (this.state.xIsNext ? 'X' : 'O')}</div>
          <ol>{(winner) ? moves : null}</ol>
        </div>
      </div>
    );
  }
}
 
ReactDOM.render(
  <Game />,
  document.getElementById('root')
);
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
0
25
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Когда вы проверяете победителя, хотя он должен быть победителем, квадраты еще не обновляются (this.handleClick действительно меняет состояние, но само изменение является асинхронным).

Я бы рекомендовал переместить проверку победителя в обработчик кликов

handleClick(i) {
  const history = this.state.history.slice(0, this.state.stepNumber + 1);
  const current = history[history.length - 1];
  const squares = current.squares.slice();
  if (squares[i]) {
    return;
  }
  squares[i] = this.state.xIsNext ? "X" : "O";
  this.setState({
    history: history.concat([
      {
        squares: squares
      }
    ]),
    stepNumber: history.length,
    xIsNext: !this.state.xIsNext,
    winner: calculateWinner(squares) // <-- this
  });
}

https://codesandbox.io/s/epic-sutherland-gj6d5?file=/src/App.js:1996-2028

Рад слышать. Не за что :)

Mosh Feu 06.04.2021 00:11

Другие вопросы по теме