Aula 07 – React – Utilizando hooks no código
Aula 07 – React – Utilizando hooks no código

Tutorial React
Voltar para página principal do blog
Todas as aulas desse curso
Aula 06 Aula 08
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_with_hooks
Link da documentação oficial:
https://reactjs.org/tutorial/
Aula 07 – React – Utilizando hooks no código
Primeiros passos com React Hooks
Antes de começar a refatorar o código do joguinho da velha para usar componente funcional com hooks, vamos falar um pouquinho sobre eles.
A equipe do React apresentou o React Hooks ao mundo na React Conf no final de outubro de 2018.
No início de fevereiro de 2019, finalmente chegou o React v16.8.0. e com ele a possibilidade de usar os hooks.
Os hooks fornecem uma forma de construir componentes funcionais com estado, assim como os componentes baseados em classe têm.
Possibilita a utilização dos métodos de ciclo de vida, permitindo que você evite usar componentes de classe e tenha um código mais modular e legível.
Mas, porque é melhor usar componentes funcionais ao invés de baseados em classes?
- O código fica mais fácil de ler, de entender, mais fácil de raciocinar e de testar.
- Você vai precisar escrever menos código;
- A equipe do React diz que pode haver um aumento de desempenho para componentes funcionais em futuras versões do React.
Agora, em casos onde seu componente precise de muitas funcionalidades, e manter muitos estados, use classes.
O Facebook, criador do React, recomenda oficialmente o uso de componentes funcionais sempre que possível.
Voltando ao código
No código do jogo da velha, temos só o Game com propriedades, o Square e o Board não tem.
Na inicialização, os campos do Board são preenchidos com null, quando o Game passa para ele via props (current.squares) a lista history na posição zero, que é o tabuleiro vazio.
O estado do Game na inicialização é esse: tabuleiro vazio, isto é, o current com tudo null, stepNumber com zero e o xIsNext como true.
A medida que o jogo vai acontecendo, os estados do Game vão sendo atualizados e renderizados na tela.
Código do Tic Tac Toe utilizando hooks e o componente Game e Board como funcional.
import React, { useState } from "react";
import ReactDOM from "react-dom";
import "./tic-tac-toe.css";
const Square = props => {
return (
<button
className="square"
onClick={props.onClick}
>
{props.value}
</button>
);
};
const Board = props => {
const renderSquare = i => {
return (
<Square
value={props.squares[i]}
onClick={() => props.onClick(i)}
/>
);
};
return (
<div>
<div className="board-row">
{renderSquare(0)}
{renderSquare(1)}
{renderSquare(2)}
</div>
<div className="board-row">
{renderSquare(3)}
{renderSquare(4)}
{renderSquare(5)}
</div>
<div className="board-row">
{renderSquare(6)}
{renderSquare(7)}
{renderSquare(8)}
</div>
</div>
);
};
const Game = props => {
const initialHistory = [
{ squares: Array(9).fill(null) }
];
const [history, setHistory] = useState(initialHistory);
const [xIsNext, setXIsNext] = useState(true);
const [stepNumber, setStepNumber] = useState(0);
const handleClick = i => {
const slicedHistory = history.slice(0, stepNumber + 1);
const finalStepInSlicedHistory = slicedHistory[slicedHistory.length - 1];
const newSquares = [...finalStepInSlicedHistory.squares];
const winnerDeclared = Boolean(calculateWinner(newSquares));
const squareAlreadyFilled = Boolean(newSquares[i]);
if (winnerDeclared || squareAlreadyFilled) return;
newSquares[i] = xIsNext ? 'X' : 'O';
const newStep = { squares: newSquares };
const newHistory = [...slicedHistory, newStep];
setHistory(newHistory);
setXIsNext(!xIsNext);
setStepNumber(slicedHistory.length);
};
const moves = history.map((step, move) => {
const description = Boolean(move)
? `Go to move #${move}`
: `Go to game start`;
return (
<li key={move}>
<button onClick={() => jumpTo(move)}>{description}</button>
</li>
);
});
const jumpTo = step => {
setStepNumber(step);
const isEvenStepNumber = step % 2 === 0;
setXIsNext(isEvenStepNumber);
};
const currentStep = history[stepNumber];
const winner = calculateWinner(currentStep.squares);
const status = winner
? `Winner: ${winner}`
: `Next player: ${xIsNext ? 'X' : 'O'}`;
return (
<div className="game">
<div className="game-board">
<Board
squares={currentStep.squares}
onClick={i => handleClick(i)}
/>
</div>
<div className="game-info">
<div>{status}</div>
<ol>{moves}</ol>
</div>
</div>
);
};
// ========================================
ReactDOM.render(
<Game />,
document.getElementById('root')
);
/**
* calculateWinner (helper function)
*
* Parameter: squares (array of 'X', '0', or null)
* Return value: 'X', 'O', or null
*/
function calculateWinner(squares) {
/* Squares indexes
0 1 2
3 4 5
6 7 8
*/
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],
]; // mostra todas as combinações vencedoras ("linhas")
// itera em todas as combinações de linhas vencedoras para ver se o array de quadrados de entrada
// se tem uma com todos 'X's ou todos ' O's. Se verdadeiro, retorna 'X' ou 'O' dependendo de quem ganhou.
for (let line of lines) {
const [a, b, c] = line;
if (
squares[a] &&
squares[a] === squares[b] &&
squares[a] === squares[c]
) {
return squares[a];
}
}
// se nenhuma das combinações de linhas vencedoras estiver contida no array de quadrados de entrada
// returna null...
return null;
}