Aula 06 – React – Mostrando as jogadas anteriores

Aula 06 – React – Mostrando as jogadas anteriores

Tutorial React

Tutorial React

Voltar para página principal do blog

Todas as aulas desse curso

Aula 05                        Aula 07

Se gostarem do conteúdo dêem um joinha 👍 na página do Código Fluente no
Facebook

Esse é o link do código fluente no Pinterest

Meus links de afiliados:

Hostinger

Digital Ocean

One.com

Melhore seu NETWORKING

Participe de comunidades de desenvolvedores:

Fiquem a vontade para me adicionar ao linkedin.

E também para me seguir no GITHUB.

Ah, se puder, clica na estrela nos meus repositórios pra dá uma força ao meu perfil no GITHUB

Código da aula:

https://github.com/toticavalcanti/tutorial-react/tree/tic_tac_toe

Link da documentação oficial:

https://reactjs.org/tutorial/

Aula 06 – React – Mostrando as jogadas anteriores

Como estamos gravando o histórico de jogadas, agora queremos exibir ele para o jogador como uma lista de jogadas anteriores.

Para renderizar vários itens no React, podemos usar uma matriz de elementos React.

Em JavaScript, os arrays têm um método map() que é comumente usado para mapear dados para outros dados, por exemplo:


const numbers = [1, 2, 3];
const doubled = numbers.map(x => x * 2); // [2, 4, 6]

Usando o método map, podemos mapear nosso histórico de jogadas para elementos React que representam botões na tela, exibir uma lista de botões e ir para jogadas anteriores.

Para cada movimento no histórico, criamos um item de lista <li> que contém um botão <button>.

O botão tem um manipulador onClick que chama um método chamado jumpTo().

Quando renderizamos uma lista, o React armazena algumas informações sobre cada item da lista renderizada.

Quando atualizamos uma lista, o React precisa determinar o que mudou.

Por causa disso, ele precisa da propriedade key, com essa propriedade, o React consegue saber quem e o que mudou.

Implementando o histórico de jogadas

No histórico do jogo, cada movimento anterior tem um ID exclusivo associado a ele, é o número sequencial do movimento.

Os movimentos nunca são reordenados, excluídos ou inseridos no meio, portanto, é seguro usar o índice de movimento como uma chave.

Adicionaremos stepNumber ao estado do componente Game para indicar qual etapa estamos visualizando no momento.

Definiremos o método jumpTo() no Game para atualizar esse stepNumber.

Também definiremos xIsNext como true se o número para o qual estamos mudando stepNumber for par.

Vamos alterar também o método handleClick() do jogo, que é disparado quando você clica em um quadrado.

O estado stepNumber reflete a movimentação exibida.

Depois de fazer um novo movimento, precisamos atualizar stepNumber adicionando:

stepNumber: history.length

Como parte do argumento this.setState.

Isso garante não parar de mostrar o mesmo movimento depois que um novo for feito.

Também substituiremos a leitura de this.state.history por this.state.history.slice (0, this.state.stepNumber + 1).

Isso garante que, se “voltarmos no tempo” e fizermos um novo movimento a partir de um ponto específico, jogaremos fora as jogadas posteriores a esse ponto escolhido, que tinham sido feitas antes.

Iremos modificar o método de renderização do componente Jogo para que a jogada atualmente selecionada esteja de acordo com stepNumber.

1 – Vamos mapear o histórico de jogadas no método de renderização do jogo;

2 – Vamos usar índice do array history como chave;

3 – Adicionaremos stepNumber ao estado do componente Game, para indicar qual etapa estamos visualizando no momento;

4 – Definiremos xIsNext como true se o número para o qual estamos mudando stepNumber for par;

5 – Substituiremos a leitura de this.state.history por this.state.history.slice (0, this.state.stepNumber + 1).

6 – Modificar o método de renderização do componente Jogo para a jogada atualmente selecionada de acordo com stepNumber.

import React from 'react';
import ReactDOM from 'react-dom';
import './tic-tac-toe.css';
function Square(props) {
  return (
    <button className="square" onClick={props.onClick}>
      {props.value}
    </button>
  );
}

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

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

  render() {
    const history = this.state.history;
    const current = history[this.state.stepNumber];
    const winner = calculateWinner(current.squares);

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

  let status;
  if (winner) {
    status = "Winner: " + winner;
  } else {
    status = "Next player: " + (this.state.xIsNext ? "X" : "O");
  }

  return (
      <div className="game">
        <div className="game-board">
          <Board
            squares={current.squares}
            onClick={i => this.handleClick(i)}
          />
      </div>
      <div className="game-info">
        <div>{status}</div>
        <ol>{moves}</ol>
      </div>
    </div>
    );
  }
}

// ========================================

ReactDOM.render(<Game />, document.getElementById("root"));

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

Na próxima aula, a gente vai refatorar o código.

Vamos alterar o componente “Game” para que ele seja componente funcional, ao invés de baseado em classe, para isso, utilizaremos hooks.

Ficamos por aqui por hora. 😉

Aula 05                        Aula 07

Todas as aulas desse curso

Voltar para página principal do blog

Código final da aula:

https://github.com/toticavalcanti/tutorial-react/tree/tic_tac_toe

Se gostarem do conteúdo dêem um joinha 👍 na página do Código Fluente no
Facebook

Link do código fluente no Pinterest

Novamente deixo meus link de afiliados:

Hostinger

Digital Ocean

One.com

Obrigado, até a próxima e bons estudos. 😉

About The Author
-

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>