Aula 02 – React – Passando dados por props

Aula 02 – React – Passando dados por props

Tutorial React

Tutorial React

Voltar para página principal do blog

Todas as aulas desse curso

Aula 01                        Aula 03

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/

Passando dados por props

No método renderSquare do Board, altere o código para passar o props chamado value para o Square:

src/index.js


class Square extends React.Component {
  render() {
    return (
      <button className="square">
        {this.props.value}
      </button>
    )
  }
}
class Board extends React.Component {
  renderSquare(i) {
      return <Square value={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'));

Passamos um “props” do componente Board, que é o pai, para um componente filho, o Square.

Preenchendo o componente Square com um “X” quando clicamos nele:

src/index.js


class Square extends React.Component {
  render() {
    return (
      <button className="square" onClick={function() { alert('click'); }}>
        {this.props.value}
      </button>
    )
}
class Board extends React.Component {
  renderSquare(i) {    
    return <Square value={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'));

Clicando em um quadrado aparecerá um alerta no seu navegador.

Refatorando a onClick para usar arrow function.

src/index.js


class Square extends React.Component {
  render() {
    return (
      <button className="square" onClick={ () => this.setState({value: 'X'}) }>
        {this.props.value}
      </button>
    )
}
class Board extends React.Component {
  renderSquare(i) {    
    return <Square value={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'));

O próximo passo, é fazer o componente Square lembrar que foi clicado e preencher com um “X”.

Para guardar o estado de clicado, usaremos o estado(state) do componente square.

Os componentes React podem ter estados, configurando o this.state em seus construtores.

O this.state deve ser considerado como privado para o componente React que o definiu.

Vamos armazenar o valor atual do Square em this.state e alterá-lo quando o Square for clicado.

Primeiro, adicionaremos um construtor à classe para inicializar o estado.

Todos os componentes de classe React que possuem um método constructor, devem iniciá-lo com uma chamada super(props).

src/index.js


class Square extends React.Component {
  constructor(props) {
      super(props);
      this.state = {
        value: null,
    };
  }
  render() {
    return (
      <button className="square" onClick={ () => this.setState({value: 'X'}) }>
        {this.props.value}
      </button>
    )
}
class Board extends React.Component {
  renderSquare(i) {    
    return <Square value={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'));

Agora vamos mudar o método render do componente Square para exibir o valor do estado (state) atual quando clicado:

  • Substitua this.props.value por this.state.value dentro da tag <button>.
  • Coloque props className e onClick em linhas separadas para melhor legibilidade.

Então vamos fazer a modificação e a reidentação.

src/index.js


class Square extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: null,
    };
  }
  render() {
    return (
      <button
        className="square"
        onClick={() => this.setState({value: 'X'})}
      >
        {this.state.value}
      </button>
    );
  }
}
class Board extends React.Component {
  renderSquare(i) {    
    return <Square value={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'));

Completando o jogo

Para completar o jogo, precisamos preencher os “X”s e os “O”s no tabuleiro(Board) e de alguma maneira necessitamos definir o vencedor.

Movendo o state para cima

Atualmente, cada componente Square mantém o estado do jogo.

Para verificar o vencedor, a melhor opção é guardar o estado do jogo no componente pai, o tabuleiro.

O componente tabuleiro pode dizer para cada quadrado o que pode ser exibido via props, assim como fizemos quando passamos o número de cada quadrado.

Para coletar dados de múltiplos filhos, ou para fazer dois filhos se comunicarem entre si, você precisa declarar um estado compartilhado em seu componente pai.

O componente pai pode passar o estado de volta para os filhos através do uso de propriedades (props), isso mantém os componentes filhos em sincronia com os seus irmãos e também com o pai.

Criar estado em um componente Pai é bem comum quando componentes React são refatorados.

Vamos aproveitar essa oportunidade para testar o conceito, na prática.

Vamos adicionar um construtor no Tabuleiro e definir que seu estado inicial irá ter um array com 9 posições preenchidas por nulo (null).

Esses 9 nulls corresponderão aos 9 quadrados:

src/index.js


class Square extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: null,
    };
  }
  render() {
    return (
      <button
        className="square"
        onClick={() => this.setState({value: 'X'})}
      >
        {this.state.value}
      </button>
    );
  }
}
class Board extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      squares: Array(9).fill(null),
    };
  }
  renderSquare(i) {    
    return <Square value={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'));

Vamos modificar o Tabuleiro para instruir cada Quadrado individualmente qual é o valor correto (‘X’, ‘O’ ou null).

Nós já temos definidos o array de quadrados no construtor do Tabuleiro e iremos modificar o método renderSquare para definir o valor a partir do estado.

Também criar a função handleClick().

Nela, nós chamamos .slice() para criar uma cópia do array de quadrados para o modificar ao invés de fazer no array existente.

Depois a gente vai ver o porquê disso.

src/index.js


class Square extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: null,
    };
  }
  render() {
    return (
      <button
        className="square"
        onClick={() => this.setState({value: 'X'})}
      >
        {this.state.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]} />;
  }
  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'));

É isso pessoal, nos vemos na próxima!

Aula 01                        Aula 03

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>