Java para Web

Aula 14 : Tópicos Especiais em React

Aula 14 - Tópicos Especiais em React

Temas relacionados ao desenvolvimento em React.js

Exemplos de aula

React Router

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-dom

O React Router possui basicamente três tipos de componentes:

  • Roteadores como BrowserRouter e HashRouter
  • Seletores como Switch e Route
  • Navegadores como Link e NavLink e Redirect

Roteadores React Router

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 o Create React App
  • HashRouter, 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:

js Usando o Router
import {BrowserRouter as Router} from 'react-router-dom'
render(){
    return(
        <Router></Router>
    )
}
Seletores React 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:

js Usando o Switch
<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

Renderização Condicional

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:

js
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:

js
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:

js
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ó.

Fragmentos no React

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:

js
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:

js
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:

js
<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:

js
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

Listas no React

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:

js
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:

js
<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.

Chaves em Listas no React

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:

js
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.