Aula 02 – React – Passando dados por props
Aula 02 – React – Passando dados por props
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'));