Aula 07 – React – Utilizando hooks no código
Aula 07 – React – Utilizando hooks no código
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;
}