Aula 03 – React – Imutabilidade

Aula 03 – React – Imutabilidade

Tutorial React

Tutorial React

Voltar para página principal do blog

Todas as aulas desse curso

Aula 02                        Aula 04

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 branch inicial:

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

Link da documentação oficial:

https://reactjs.org/tutorial/

Por que imutabilidade é Importante

No código do exemplo usamos o método slice() para criar uma cópia do array de quadrados ao invés de modificar o existente.

Iremos agora discutir imutabilidade e porque ela é importante de se aprender.

Geralmente existem duas maneiras de se alterar dados.

A primeira é mudar (mutar) o dado alterando diretamente seu valor.

A segunda maneira é substituir o dado antigo por uma nova cópia com as alterações desejadas.

Mudando dados com mutação


let player = {score: 1, name: 'Jeff'};
player.score = 2;
// Agora o player é {score: 2, name: 'Jeff'}

Mudando dados sem mutação


let player = {score: 1, name: 'Jeff'};

let newPlayer = Object.assign({}, player, {score: 2});
// Agora o player não sofreu alteração, mas o newPlayer é {score: 2, name: 'Jeff'}

// Ou então se você estiver usando a sintaxe "object spread", você pode escrever:
// let newPlayer = {...player, score: 2};

O resultado final é o mesmo, mas, por não mudar (ou alterar os dados) diretamente, ganhamos vários benefícios.

Complexidade das features se tornam mais simples

Imutabilidades faz a complexidade das features se tornarem bem mais simples de serem implementadas.

Mais a frente, implementaremos uma feature de “máquina do tempo” que nos permitirá revisar o histórico do jogo da velha e “voltar” as jogadas anteriores.

Essa funcionalidade não está ligada somente ao jogo, uma habilidade de desfazer e refazer certas ações é um requisito comum em aplicações.

Evitar mutação nos permite manter o histórico das versões anteriores do jogo intacta e reutiliza-las mais tarde.

Detectar Mudanças

Detectar mudanças e objetos que foram mudados é difícil, pois, eles são modificados diretamente.

Essa detecção requer um objeto que foi alterado para ser comparado com as cópias das suas próprias versões anteriores e a árvore inteira do object para ser cruzada.

Detectar mudanças em objetos imutáveis é consideravelmente fácil.

Se ele for imutável e o que está sendo referenciado for diferente do anterior, concluímos que o objeto foi alterado.

Determinar Quando Re-renderizar no React

O principal benefício da imutabilidade é que ela ajuda a construir componentes puros em React.

Dados imutáveis podem facilmente determinar se foram feitas mudanças, que ajudarão a decidir quando um componente precisa ser renderizado novamente.

Componentes de Função

Nós vamos agora mudar o Square para ser um componente de função.

Em React, componentes de função são os mais simples de serem escritos, contém apenas um método render e não possuem seu próprio state.

Ao invés de definir uma classe que extende de React.Component, nós podemos escrever uma função que recebe props como entrada e retorna o que deverá ser renderizado.

Esse tipo de componente é menos tedioso de escrever do que classes e muitos componentes podem ser expressados desta maneira.

Troque a classe Square por esta função:

src/index.js


function Square(props) {
  return (
    <button className="square" onClick={props.onClick}>
      {props.value}
    </button>
  );
}
class Board extends React.Component {
  constructor(props) { 
    super(props); 
    this.state = { 
      squares: Array(9).fill(null),
  };
  handleClick(i) { 
    const squares = this.state.squares.slice(); 
    squares[i] = 'X'; this.setState({squares: squares}); }
  renderSquare(i) {    
    return <Square value={this.state.squares[i]} />;
  }
  renderSquare(i) {
    return (
      <Square
        value={this.state.squares[i]}
        onClick={() => this.handleClick(i)}
      />
    );
  }
  render() 
    const status = 'Next player: X';
    return (
      React.createElement("div", null,
      React.createElement("div", { className: "status" }, status),
      React.createElement("div", { className: "board-row" },
      this.renderSquare(0),
      this.renderSquare(1),
      this.renderSquare(2)),
      React.createElement("div", { className: "board-row" },
      this.renderSquare(3),
      this.renderSquare(4),
      this.renderSquare(5)),
      React.createElement("div", { className: "board-row" },
      this.renderSquare(6),
      this.renderSquare(7),
      this.renderSquare(8))));
  }
}
class Game extends React.Component {
  render() {
    return (
      React.createElement("div", { className: "game" },
      React.createElement("div", { className: "game-board" },
      React.createElement(Board, null)),
      React.createElement("div", { className: "game-info" },
      React.createElement("div", null),
      React.createElement("ol", null))));
  }
}
// ========================================
ReactDOM.render(
React.createElement(Game, null),
document.getElementById('root'));

Nos modificamos this.props para props nas duas vezes em que ele aparece.

Nota

Quando modificamos Square para ser um componente funcional, também modificamos onClick={() => this.props.onClick()} para uma versão mais curta:

onClick={props.onClick}

Note a ausência dos parentêses em ambos os lados.

Alternando os jogadores

Agora precisamos consertar um defeito óbvio em nosso Jogo da Velha:
Os “O“s não podem ser marcados no tabuleiro.

Vamos definir a primeira jogada para ser “X” por padrão.

Podemos definir esse padrão modificando o state inicial no construtor do nosso tabuleiro (Board).

src/index.js


function Square(props) {
  return (
    <button className="square" onClick={props.onClick}>
    {props.value}
    </button>
 );
}
class Board extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      squares: Array(9).fill(null),
      xIsNext: true,
    };
  }
  handleClick(i) { 
    const squares = this.state.squares.slice(); 
    squares[i] = 'X'; this.setState({squares: squares}); }
    renderSquare(i) {    
      return <Square value={this.state.squares[i]} />;
  }
  renderSquare(i) {
    return (
      <Square
        value={this.state.squares[i]}
        onClick={() => this.handleClick(i)}
      />
    );
  }
  render() 
    const status = 'Next player: X';
    return (
      React.createElement("div", null,
      React.createElement("div", { className: "status" }, status),
      React.createElement("div", { className: "board-row" },
      this.renderSquare(0),
      this.renderSquare(1),
      this.renderSquare(2)),
      React.createElement("div", { className: "board-row" },
      this.renderSquare(3),
      this.renderSquare(4),
      this.renderSquare(5)),
      React.createElement("div", { className: "board-row" },
      this.renderSquare(6),
      this.renderSquare(7),
      this.renderSquare(8))));
  }
}
class Game extends React.Component {
  render() {
    return (
      React.createElement("div", { className: "game" },
      React.createElement("div", { className: "game-board" },
      React.createElement(Board, null)),
      React.createElement("div", { className: "game-info" },
      React.createElement("div", null),
      React.createElement("ol", null))));
  }
}
// ========================================
ReactDOM.render(
React.createElement(Game, null),
document.getElementById('root'));

Sempre que um jogador fizer uma jogada, xIsNext (um boolean) será trocado para determinar qual jogador será o próximo e o state do jogo será salvo.

Nós atualizaremos a função handleClick() do Board para trocar o valor de xIsNext:

src/index.js


function Square(props) {
  return (
    <button className="square" onClick={props.onClick}>
    {props.value}
    </button>
 );
}
class Board extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      squares: Array(9).fill(null),
      xIsNext: true,
    };
  }
  handleClick(i) {
    const squares = this.state.squares.slice();
    squares[i] = this.state.xIsNext ? 'X' : 'O';
    this.setState({
      squares: squares,
      xIsNext: !this.state.xIsNext,
    });
  }
  renderSquare(i) {
    return (
      <Square
        value={this.state.squares[i]}
        onClick={() => this.handleClick(i)}
      />
    );
  }
  render() 
    const status = 'Next player: X';
    return (
      React.createElement("div", null,
      React.createElement("div", { className: "status" }, status),
      React.createElement("div", { className: "board-row" },
      this.renderSquare(0),
      this.renderSquare(1),
      this.renderSquare(2)),
      React.createElement("div", { className: "board-row" },
      this.renderSquare(3),
      this.renderSquare(4),
      this.renderSquare(5)),
      React.createElement("div", { className: "board-row" },
      this.renderSquare(6),
      this.renderSquare(7),
      this.renderSquare(8))));
  }
}
class Game extends React.Component {
  render() {
    return (
      React.createElement("div", { className: "game" },
      React.createElement("div", { className: "game-board" },
      React.createElement(Board, null)),
      React.createElement("div", { className: "game-info" },
      React.createElement("div", null),
      React.createElement("ol", null))));
  }
}
// ========================================
ReactDOM.render(
React.createElement(Game, null),
document.getElementById('root'));

Com essa mudança,”X“s e “O“s serão alternados.

Tente!

Também vamos modificar o texto de “status” na função render() do Board, para que ela passe a exibir quem jogará no próxima jogada.

src/index.js


function Square(props) {
  return (
    <button className="square" onClick={props.onClick}>
    {props.value}
    </button>
 );
}
class Board extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      squares: Array(9).fill(null),
      xIsNext: true,
    };
  }
  handleClick(i) {
    const squares = this.state.squares.slice();
    squares[i] = this.state.xIsNext ? 'X' : 'O';
    this.setState({
      squares: squares,
      xIsNext: !this.state.xIsNext,
    });
  }
  renderSquare(i) {
    return (
      <Square
        value={this.state.squares[i]}
        onClick={() => this.handleClick(i)}
      />
    );
  }
  render() 
    const status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');
    return (
      React.createElement("div", null,
      React.createElement("div", { className: "status" }, status),
      React.createElement("div", { className: "board-row" },
      this.renderSquare(0),
      this.renderSquare(1),
      this.renderSquare(2)),
      React.createElement("div", { className: "board-row" },
      this.renderSquare(3),
      this.renderSquare(4),
      this.renderSquare(5)),
      React.createElement("div", { className: "board-row" },
      this.renderSquare(6),
      this.renderSquare(7),
      this.renderSquare(8))));
  }
}
class Game extends React.Component {
  render() {
    return (
      React.createElement("div", { className: "game" },
      React.createElement("div", { className: "game-board" },
      React.createElement(Board, null)),
      React.createElement("div", { className: "game-info" },
      React.createElement("div", null),
      React.createElement("ol", null))));
  }
}
// ========================================
ReactDOM.render(
React.createElement(Game, null),
document.getElementById('root'));

Por essa aula é só! 😉

Aula 02                        Aula 04

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>