Aula 14 - Tópicos Especiais em React
Temas relacionados ao desenvolvimento em React.js
Exemplos de aula
React Router
O React Router é uma coleção de componentes que possibilitam a navegação dentro de uma aplicação React. Para instalar o React Router, utilize:
npm install react-router-domO React Router possui basicamente três tipos de componentes:
- Roteadores como
BrowserRoutereHashRouter - Seletores como
SwitcheRoute - Navegadores como
LinkeNavLinkeRedirect
Os roteadores são o componente básico do React Router. Existe dois tipos de roteadores principais, que são:
BrowserRouter, usa URL regular. Precisa de configuração adicional em caso de uso sem oCreate React AppHashRouter, armazena a localização na porção de hash da URL. Não envia o hash para o servidor e por isso não precisa de comunicação adicional.
Não há de fato casos de uso limitados para ambos os componentes. A grande diferença entre os dois está no fato de que ao contrário de BrowserRouter, o HashRouter impede o navegador de realizar um novo GET quando há atualização da URL.
O router será o componente principal na estrutura de roteamento:
import {BrowserRouter as Router} from 'react-router-dom'
render(){
return(
<Router></Router>
)
}
Os Seletores possuem o papel de "casar" rotas com componentes. Estão imediatamente abaixo do Router e são usados de forma conjunta. Cada rota é representado por um componente Route, usando o atributo path. O Switch garante que apenas a primeira rota a casar com a URL será utilizada:
<Router>
<Switch>
<Route path="/about">
{"Página não existe"}
</Route>
<Route path="/">
<Pagina />
</Route>
</Switch>
</Router>
No exemplo acima, será renderizada a string Página não existe quando a URL for igual a /about. Para todos os outros casos, será renderizado o componente Pagina, já que a URL / casa com todos os outros casos. Note que para /about, o componente página não é renderizado pois já há uma rota superior casada com a URL.
Outros Tópicos
O uso do JSX permite o uso integrado de estruturas de seleção e repetição. Podemos, por exemplo, criar uma função que retorna um elemento diferente dependendo da sua entrada:
boasVindas = (logado) => {
if(logado){
return <BoasVindasLogado></BoasVindasLogado>
}
else{
return <BoasVindasDeslogado></BoasVindasDeslogado>
}
}
Os elementos podem ser armazenados em variáveis, dessa forma, podemos usá-los de forma simplificada na renderização:
render(){
var resultado = null
if (this.props.admin){
resultado = <AdminPage></AdminPage>
}
return resultado
}
Por fim, também podemos usar essa técnica para concatenar elementos:
render(){
var resultado = null
if (this.props.admin){
resultado = <AdminPage></AdminPage>
}
<mark class="highlight-inline">resultado = <section>{resultado}</section></mark>
return resultado
}
Lembre-se que o resultado do render só pode ser um único elemento. Este elemento pode ter diversos filhos, porém é obrigatório que a raiz dos elementos seja uma só.
Como já citado, o resultado do render deve ser sempre um único elemento, não importando quantos filhos ele possui. Isso nos obriga a criar um elemento raiz sempre que desejamos retornar mais de um elemento na renderização, por exemplo:
render(){
return(
<div>
<MainPage></MainPage>
<SideBar></SideBar>
</div>
)
}
No entanto, essa estratégia pode ser inconveniente, já que pode exigir a criação de elementos desnecessários ou que não possuem boa acomplagem à outros componentes. Em alguns casos, essa estrutura poderia tornar um componente completamente disfuncional. Acompanhe o exemplo abaixo:
class Tabela{
render(){
var linhaTabela = <LinhaTabela></LinhaTabela>
return(
<table>
<tr>
{linhaTabela}
</tr>
</table>
)
}
}
class LinhaTabela{
render(){
return(
<div>
<td>1</td>
<td>CPF</td>
</div>
)
}
}
O uso de um elemento como div na renderização acima é necessário, já que não é possível retornar a dupla de td diretamente no render. No entanto, isso faz com que a tabela não seja renderizada corretamente, já que a sua estrutura deve ficar assim:
<table>
<tr>
<div>
<td>1</td>
<td>CPF</td>
</div>
</tr>
</table>
Para resolver este problema, podemos usar o React.Fragment, uma espécie de pseudo-componente que não é renderizado no DOM. Sua função é apenas encapsular elementos:
class LinhaTabela{
render(){
return(
<React.Fragment>
<td>1</td>
<td>CPF</td>
</React.Fragment>
)
}
}
Outra opção é utilizar simplesmente os elementos <> e </>, que é uma forma reduzida de especificar um fragmento
Para produzir listas de elementos, podemos utilizar função map. Geralmente, criamos uma estrutura para receber e gerar os elementos a partir de um vetor, muito parecido com isto:
render(){
var boys = ["butcher", "hughie", "mother's milk", "frenchie", "kimiko"]
var lista = boys.map((valor)=>{
return <Personagem nome={valor}>
})
return lista
}
No exemplo acima, os componentes renderizados devem ser:
<Personagem nome="butcher"></Personagem>
<Personagem nome="hughie"></Personagem>
<Personagem nome="mother's milk"></Personagem>
<Personagem nome="frenchie"></Personagem>
<Personagem nome="kimiko"></Personagem>
Executar esse código causa um aviso de chave no console. Iremos verificar o uso de chaves em listas a seguir.
Ao renderizar uma lista de componentes, o React realiza sua alteração de forma única, como um único elemento. Para que possamos atualizar elementos de uma lista de maneira individual, vamos utilizar um atributo chamado key, que é usado pelo React apenas para identificar itens alterados ou removidos de uma lista:
render(){
var items = [
{_id: "ac9a8b098c090c90", "name": "Goku"},
{_id: "ac9a8b098c090c91", "name": "Picollo"},
{_id: "ac9a8b098c090c92", "name": "Frezza"},
{_id: "ac9a8b098c090c93", "name": "Gohan"},
{_id: "ac9a8b098c090c94", "name": "Mr. Satan"}
]
var lista = items.map((valor)=>{
return <Personagem nome={valor.name} key={valor._id}>
})
return lista
}
Recomenda-se o uso de um ID estável para cada item de uma lista. Isso garante que o React terá controle total sobre a atualização da lista, realizando novamente a renderização apenas de itens únicos alterados. Em casos onde não existe nenhum tipo de identificador único, uma última alternativa é usar o índice do vetor como key, no entanto, essa alternativa não é recomendada (Explicação aprofundada sobre impactos negativos de usar o índice).
Outro ponto importante é que o atributo key não será inserido no DOM, sendo usado apenas no controle interno do React.