07 Apostila React Forms Eventos Listas
07 Apostila React Forms Eventos Listas
https://www.rodrigobossini.com.br
ReactJS
Forms, entrada de dados, eventos, acesso a APIs e listas
1 Introdução
Veja a aplicação a ser desenvolvida. Ela oferece um campo em que o usuário pode
digitar um termo de busca qualquer como “animais”, “pessoas”, “roupas”. A seguir,
se encarrega de exibir uma lista de figuras condizentes com a sua busca.
2 Desenvolvimento
Use
cd nome-projeto
code .
para obter uma instância do VS Code vinculada a esse diretório. No VS Code, clique
Terminal >> New Terminal para obter um novo terminal interno do VS Code, o que
simplifica o trabalho. Neste terminal, digite
npm start
Apague todos os arquivos existentes na pasta src. A seguir, crie uma pasta chamada
components, subpasta de src. Definiremos todos os componentes dessa aplicação
em arquivos dentro dela.
Na pasta components, crie um arquivo chamado App.js. Veja seu conteúdo inicial.
Optamos por um componente funcional pois não precisaremos de estado
inicialmente.
Nota. Lembre-se que, até então, não estudamos sobre os Hooks do React, então, se
precisarmos de componentes com estado, utilizaremos aqueles definidos por meio
de classes.
Crie um arquivo chamado index.js na pasta src, fora da pasta components. Veja seu
conteúdo a seguir. Note que estamos “montando” o componente App tal qual feito
em outras aplicações.
ReactDOM.render(
<App />,
document.querySelector('#root')
)
PrimeReact
https://www.primefaces.org/primereact/
PrimeFlex
https://www.primefaces.org/primeflex/
</div>
)
}
}
Busca.defaultProps ={
dica: 'Digite algo que deseja ver...'
}
render(){
return (
<div className="grid justify-content-center m-auto w-9 border-
round border-1 border-400">
<div className='col-12'>
<h1>Exibir uma lista de...</h1>
</div>
<div className="col-8">
<Busca />
</div>
</div>
)
}
}
export default App
/>
</span>
<Button
label="OK"
className="p-button-outlined mt-2"
/>
</div>
)
}
}
Busca.defaultProps ={
dica: 'Digite algo que deseja ver...'
}
https://reactjs.org/docs/forms.html#controlled-components
https://reactjs.org/docs/uncontrolled-components.html
https://en.wikipedia.org/wiki/Single_source_of_truth
2.5 (Usando um form) Vamos ajustar a aplicação para que ela faça uso de um
elemento HTML form. Veja.
/>
</span>
<Button
label="OK"
className="p-button-outlined mt-2"
/>
</div>
</form>
)
}}
Digite algum texto e aperte Enter. Clique também no botão. Repare que o form tem
comportamento padrão: o navegador tenta submetê-lo a um servidor e a tela
“pisca”. Desejamos evitar esse funcionamento padrão e especificar uma função que
será executada uma vez que o form seja submetido. Assim, temos a chance de
executar código antes de a requisição acontecer. Além disso, podemos fazer uma
requisição assíncrona e atualizar somente as partes da página que, de fato, tiverem
algum conteúdo novo para exibir. Veja o ajuste a seguir.
}
...
render() {
return (
<form onSubmit={this.onFormSubmit}>
...
2.6 (Função para realizar a busca) Digamos que a função que realiza a busca seja
definida pelo componente App. Para que ela entre em execução no momento
oportuno, precisamos passá-la – via props – ao componente Busca. Defina a função
no componente App assim. Observe que ele foi redefinido, agora utilizando uma
classe.
Agora, faça com que o componente Busca a coloque em execução no momento certo.
Veja.
}
...
Teste a aplicação novamente. Após digitar algum texto e clicar no botão, o console
do navegador deverá exibir aquilo que foi digitado.
2.7 (Pexels) Pexels é um site bastante utilizado para a obtenção de figuras de alta
qualidade e gratuitas. É possível acessar a sua página oficial como um usuário
regular e fazer buscas e obtenções de figuras. Também é possível acessar a base
de dados por meio de uma API. O primeiro passo para isso é visitar a seguinte
página.
https://www.pexels.com/api/
Será necessário criar uma conta ou fazer login com alguma rede social. Uma vez que
esteja logado, visite a mesma página uma vez mais e clique Your API Key para
visualizar a sua chave. A seguir, aprenderemos uma forma interessante de adicioná-
la ao projeto.
2.8 (.env para projetos React) A chave para acesso ao site Pexels é um exemplo
de “variável de ambiente”. Trata-se de um valor que pode mudar conforme a
aplicação muda de estágios (desenvolvimento, teste, produção etc.). Além disso, é
uma chave que, evidentemente, não desejamos compartilhar em repositórios
públicos. Em situações como essa, utilizamos um pacote clássico chamado dotenv. A
ideia consiste em criar um arquivo chamado .env – daí o nome do pacote –
responsável por abrigar as variáveis que têm características como essas descritas.
O pacote se encarrega de configurar os valores para que eles possam ser acessados
pelos componentes ser que tenham que ser mencionados explicitamente. Para
aplicações React, utilizaremos o pacote chamado react-dotenv. Visite a sua página
a seguir.
https://www.npmjs.com/package/react-dotenv
Crie um arquivo chamado .env na raiz do seu projeto, ao lado das pastas src, public
etc. Adicione a ele esse conteúdo aqui.
{
"name": "pessoal_react_lista_de_figuras",
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^11.2.7",
"@testing-library/user-event": "^12.8.3",
"primeflex": "^3.0.1",
"primeicons": "^4.1.0",
"primereact": "^6.5.1",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-dotenv": "^0.1.3",
"react-scripts": "4.0.3",
"react-transition-group": "^4.4.2",
"web-vitals": "^1.1.2"
},
"scripts": {
"start": "react-dotenv && react-scripts start",
"build": "react-dotenv && react-scripts build",
"serve": "react-dotenv && serve build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"react-dotenv": {
"whitelist": ["PEXELS_KEY"]
}
}
npm start
...
Ambas são as formas são equivalentes. Assim que a aplicação for colocada em
execução, você deverá ver a sua chave – duas ocorrências – no console do seu
navegador. Feitos os testes, você pode remover as linhas mencionadas.
https://www.pexels.com/api/documentation/
Todos os recursos podem ser acessados por requisições HTTP comuns. Entretanto,
também é possível utilizar uma biblioteca mantida oficialmente pela Pexels para
simplificar as operações. Ela pode ser instalada com
componentDidMount(){
this.pexelsClient = createClient(env.PEXELS_KEY)
}
Repare que o resultado é um objeto JSON que tem uma propriedade chamada
photos. Analise a figura a seguir para entender melhor os detalhes de cada objeto
JSON pertencente à coleção associada à chave photos.
A seguir, ajustamos o método render para que a JSX resultante inclua um elemento
para cada imagem. Para tal, utilizamos a função map do Javascript para, como o
nome sugere, mapear cada elemento da lista à JSX de interesse. Veja.
Repare que as fotos estão alinhadas à esquerda e que cada uma tem um tamanho
específico. Em breve faremos com que elas sejam dispostas de uma maneira
interessante na tela, aplicando o efeito “tile”.
Passe a exibir a lista de figuras utilizando o componente criado para tal. Isso deve
ser feito no arquivo App.js. Veja.
https://www.pexels.com/api/documentation/
Desta forma, vamos criar um componente para exibir seu logo. Na pasta
components, clique com o direito e crie um arquivo chamado PexelsLogo.js. Veja seu
conteúdo logo a seguir.
…
import PexelsLogo from './PexelsLogo'
export default class App extends React.Component {
…
render(){
return (
<div className="grid justify-content-center m-auto
w-9 border-round border-1 border-400">
<div className="col-12">
<PexelsLogo/>
</div>
<div className="col-12">
<h1 className="text-
center">Exibir uma lista de...</h1>
</div>
<div className="col-8">
<Bus-
ca onBuscaRealizada={this.onBuscaRealizada}/>
</div>
<div className="col-8">
<ListaImagens pics={this.state.pics}/>
</div>
</div>
)
}
https://www.npmjs.com/package/axios
https://github.com/axios/axios
https://axios-http.com/
A documentação da Pexels nos mostra que a URL base para todas as requisições é
https://api.pexels.com/v1/
/search
https://www.pexels.com/api/documentation/?#photos-search
Para começar a utilizar a axios, clique com o direito na pasta src e crie uma pasta
chamada utils. Nesta nova pasta, crie um arquivo chamado pexelsClient.js. Veja o
conteúdo do arquivo em que utilizamos a axios.
Para utilizar o novo cliente, ajuste o arquivo App.js assim. Repare que comentamos
a implementação do método onBuscaRealizada e fizemos uma nova. Também foi
comentada a definição do objeto pexelsClient, que utilizávamos anteriormente.
...
import pexelsClient from '../utils/pexelsClient'
export default class App extends React.Component {
// onBuscaRealizada = (termo) => {
// this.pexelsClient.photos.search({
// query: termo
// })
// .then(pics => this.setState({pics: pics.photos}))
// }
// pexelsClient = null
2.14 (Exibindo as figuras como um grid) A aplicação exibe as figuras uma abaixo
da outra. O resultado não é muito agradável visualmente. Vamos utilizar algumas
classes da PrimeFlex para fazer a disposição das figuras como em um grid.
Começamos ajustando o componente App, no arquivo App.js. Tanto a div que abriga
o componente Busca quanto a div que abriga o componente ListaImagens terão
direito a 12 colunas. O segundo, em particular, terá um grid da PrimeFlex aninhado.
Ele se encarrega de enviar, via props, os nomes das classes que serão utilizadas na
distribuição de colunas, como descrito. Veja.
...
export default class App extends React.Component {
...
render(){
return (
<div className="grid justify-content-center m-auto w-9 border-
round border-1 border-400">
<div className="col-12">
<PexelsLogo/>
</div>
<div className="col-12">
<h1 className="text-
center">Exibir uma lista de...</h1>
</div>
<div className="col-12">
<Busca onBuscaRealizada={this.onBuscaRealizada}/>
</div>
<div className="col-12">
<div className="grid">
<ListaImagens imgStyle={'col-12 md:col-6 lg:col-
4 xl:col-3'} pics={this.state.pics}/>
</div>
</div>
</div>
)
}
Pronto. Faça novos testes. Faça uma busca e redimensione a janela do navegador
horizontalmente para obter resultados como os seguintes.
Repare que agora o navegador exibe uma espécie de dispositivo móvel ao lado. Você
pode selecionar entre diferentes modelos, com diferentes quantidades de pixels,
para visualizar os resultados. Para isso, clique como a seguir.
Ele aparece com 1024 pixels de largura, por isso é considerado “grande”. Três
figuras são exibidas lado a lado, portanto. Por outro lado, veja o resultado do Nest
Hub Max. Ele tem 1280px de largura e é considerado extragrande. Mostra,
portanto, quatro figuras lado a lado.
Referências