A biblioteca React.js foi lançada em 2013 pelo Facebook. Seu foco não é ser um framework completo como o Angular e sim ser somente o “V” do MVC (Model View Controller) focando apenas na criação de componentes visuais.
O React é uma biblioteca para criação de interface e representa a camada de “View” em um modelo de projeto. Essa camada de visualização é criada a partir de componentes que representam funcionalidades isoladas em um sistema. Desenvolvida e disponibilizada pelo Facebook, o React é uma lib de código aberto e é mantida por milhares de desenvolvedores ao redor do mundo que contribuem de forma voluntária ao projeto.
O ReactJS foi criado pelo Facebook e inicialmente lançado como código aberto em maio de 2013. A história por trás do React é interessante, pois reflete os desafios e as necessidades específicas enfrentadas pelo Facebook na época.
O Facebook, como uma das maiores redes sociais do mundo, enfrentava o desafio de lidar com interfaces complexas e dinâmicas, como o feed de notícias, comentários em tempo real, atualizações constantes de conteúdo e interações de usuário rápidas e fluidas. Essas demandas exigiam uma abordagem mais eficiente para renderização de interfaces de usuário em tempo real, especialmente em dispositivos móveis.
A ideia do React surgiu como uma resposta a esses desafios. Jordan Walke, um engenheiro do Facebook, foi o principal criador do React. Ele começou a trabalhar em uma biblioteca interna chamada "FaxJS" para melhorar a renderização de interfaces de usuário no Facebook. Mais tarde, esse projeto evoluiu para o que conhecemos hoje como React.
O React introduziu conceitos inovadores, como a manipulação eficiente do DOM por meio da virtualização, o uso de componentes reutilizáveis e a abordagem declarativa para construir interfaces de usuário. Esses conceitos permitiram que os desenvolvedores criassem aplicativos mais rápidos, escaláveis e fáceis de manter.
Com o tempo, o React ganhou popularidade não apenas dentro do Facebook, mas também na comunidade de desenvolvedores externos. O Facebook lançou o React como código aberto em 2013, permitindo que desenvolvedores de todo o mundo utilizassem e contribuíssem para a evolução da biblioteca.
Atualmente, o React é uma das bibliotecas JavaScript mais populares e amplamente utilizadas para o desenvolvimento de interfaces de usuário modernas e interativas em aplicações web e móveis. Sua comunidade ativa, documentação abrangente e suporte contínuo de desenvolvimento o tornaram uma escolha preferida para muitos desenvolvedores e empresas.
Em 2015, o Facebook anunciou o módulo React Native, que em conjunto com o React, possibilita o desenvolvimento de aplicativos para Android e iOS utilizando componentes de interface de usuário nativos de ambas plataformas, sem precisar recorrer ao HTML.
React faz com que a criação de UIs interativas seja uma tarefa fácil. Crie views simples para cada estado na sua aplicação, e o React irá atualizar e renderizar de forma eficiente apenas os componentes necessários na medida em que os dados mudam.
Views declarativas fazem com que seu código seja mais previsível e simples de depurar.
Crie componentes encapsulados que gerenciam seu próprio estado e então, combine-os para criar UIs complexas.
Como a lógica do componente é escrita em JavaScript e não em templates, você pode facilmente passar diversos tipos de dados ao longo da sua aplicação e ainda manter o estado fora do DOM.
Os componentes do React implementam um método render() que recebe os dados de entrada e retornam o que deve ser exibido. Este exemplo usa uma sintaxe parecida com XML chamada JSX. Os dados de entrada que são passados para o componente podem ser acessados no render() via this.props.
A principal diferença do React e de outras bibliotecas baseadas em componentes diante de libs como o jQuery, Angular 1 ou Javascript puro está em sua habilidade de separar as funcionalidades do software em componentes, mas o que são componentes?
Componentes são conjuntos isolados de lógica (Javascript), visualização (JSX/HTML) e possível estilização (CSS).
Imagine a timeline do Facebook (grande case que originou o React), você roda a barra de rolagem até conter 500 posts em tela e então adiciona um comentário ao post de nº 250, imagine o quão trabalhoso é para a DOM do seu navegador entender que um único elemento no meio de tantos foi atualizado e enviar essa informação em tempo-real para os outros usuários do Facebook, ou até ouvir a atualização de 500 posts em tela de forma organizada, imagine controlar tudo isso com jQuery ou Javascript puro, será que é possível?
Separando os posts em componentes, cada item controla suas próprias informações e assim quando uma dessas publicações sofre alteração, seja comentário ou atualização em tempo real, a única que ela enxerga é a si mesmo e não precisa varrer toda DOM procurando pelo item correto a se atualizar.
Utilizando o conceito de componente, vamos visualizar a conversão dessa interface abaixo em componentes:
Veja que tudo que é visível ao usuário final da aplicação é obrigatoriamente um componente e os dividimos de forma a encapsular a lógica e estilização do mesmo, assim evitando o compartilhamento desnecessário de código entre outros componentes.
Os componentes do React implementam um método render() que recebe os dados de entrada e retornam o que deve ser exibido. Este exemplo usa uma sintaxe parecida com XML chamada JSX. Os dados de entrada que são passados para o componente podem ser acessados no render() via this.props.
Basicamente uma aplicação SPA significa você codificar menos no server-side e mais no client-side, mas como isso? A aplicação estará quase toda no cliente, sendo que assim que o usuário acesso o site a aplicação e seus templates são armazenados no lado cliente, muito diferente da forma tradicional, onde o usuário visita várias páginas diferentes.
As aplicações e os sites SPA, fazem uma transição entre os templates carregados, sem reload de página e sem que o usuário viaje de uma página para outra.
O ECMAScript (ES) é a especificação da linguagem de script que o JavaScript implementa, ou seja, é a descrição formal e estruturada de uma linguagem de script, sendo padronizada pela Ecma International – associação criada em 1961 dedicada à padronização de sistemas de informação e comunicação – na especificação ECMA-262. No dia 17 de junho de 2015, foi definida a sexta edição da especificação, a ES6 (também chamada de ECMAScript 2015).
Diferentemente das edições anteriores, o ES6 trouxe a maior mudança para a linguagem JavaScript desde a sua criação, há 20 anos. O principal objetivo da nova versão especificação foi tornar a linguagem mais flexível, enxuta e fácil de se aprender e trabalhar, tornando-a mais próxima a outras linguagens orientadas a objeto, como Java e Python.
npm install -g create-react-app
create-react-app nome_do_projeto
npx create-react-app projeto01
"scripts": {
"start": "set PORT=3006 && PORT=3006 react-scripts start || react-scripts start",
npm start
No terminal:
Compiled successfully!
You can now view <project_name> in the browser.
Local: http://localhost:3000/
On Your Network: http://<your_ip_address>:3000/
Note that the development build is not optimized.
To create a production build, use yarn build.
create-react-app --version
Os componentes funcionais tem como função receber um objeto “props” como argumento e retornar um elemento React sem se importar com o estado da aplicação. Esse tipo de componente é chamado de funcional porque é basicamente uma função JavaScript. Um componente funcional também é chamado de “apresentacional”, “mudo” ou “sem estado”.
import React from 'react';
const person = () => {
return <h1>Person Name</h1>
};
export default person;
Os componentes de classe precisam estar cientes do estado da aplicação, de acordo com determinada ação do usuário(como clicar em um botão) o componente deve responder de alguma forma. O componente de classe também é conhecido como “container”, “smart” ou “stateful”.
import React, { Component } from 'react';
class Person extends Component {
render() {
return (
<h1>Person Name!</h1>
);
}
}
export default Person;
Props é um objeto passado por um componente pai para um componente filho, e contém todas as informações relevantes para aquele componente.
O estado de um componente React é um objeto JavaScript responsável por armazenar e reagir aos eventos do usuário. Todo componente de classe tem seu próprio objeto de estado possibilitando assim, sempre que o estado de um componente for alterado, o componente e seus filhos serão renderizados novamente.
Para inicializarmos o estado inicial de um componente de classe, fazemos a definição no método construtor e para acessar o estado usamos this.state:
import React, { Component } from 'react';
class Person extends Component {
constructor(props) {
super(props);
this.state = {name: 'Thiago'}
}
render() {
return (
<h1>Person Name: {this.state.name}</h1>
);
}
}
export default Person;
Quando o componente possui um método construtor, é obrigatória a chamada ao método super(), pois o componente é uma subclasse da classe Component. Para usar this.props no contexto do método construtor é preciso passar props como parâmetro para o método super().
é o container que armazena e centraliza o estado geral da aplicação. Ela é imutável, ou seja, nunca se altera, apenas evolui.
são fontes de informações que são enviadas da aplicação para a Store. São disparadas pelas Action Creators, que são simples funções que, ao serem executadas, ativam os Reducers.
recebem e tratam as informações para que sejam ou não enviadas à Store.
para poderem se inscrever à evolução de estados da Store ou disparar eventos para evoluí-la.
Nos componentes React é possível declarar métodos que serão chamados automaticamente em certas ocasiões durante o ciclo de vida. Para entendermos todo o ciclo de vida, é preciso diferenciar as ações ocorridas em cada fase como a fase de criação, mudança no estado e mudança no objeto props.
O fluxo de mudança de estado é praticamente o mesmo fluxo disparado pelas alterações em props, com exceção que não há uma chamada ao método componentWillReceiveProps. Alterações em props podem causar uma mudança no state, mas o oposto não pode ocorrer. Se for preciso executar operações após uma mudança de estado devemos utilizar o método componentWillUpdate.
npm i react-router-dom --save
npm install axios
npm i popper.js --save
npm i bootstrap --save
npm i jquery --save
O Redux simplifica a evolução de estados de uma aplicação quando há múltiplos estados para controlar e muitos componentes que precisam atualizar ou se inscrever nessa evolução, tirando a responsabilidade de cada componente de guardar o estado e passando para uma centralizada e única Store.
Fluxo de evolução de estado
é o container que armazena e centraliza o estado geral da aplicação. Ela é imutável, ou seja, nunca se altera, apenas evolui.
são fontes de informações que são enviadas da aplicação para a Store. São disparadas pelas Action Creators, que são simples funções que, ao serem executadas, ativam os Reducers.
recebem e tratam as informações para que sejam ou não enviadas à Store.
para poderem se inscrever à evolução de estados da Store ou disparar eventos para evoluí-la.
Biblioteca React para desenvolvimento de formulários através do Redux. É capaz de integrar as ações de formulário ao state da aplicação, incluir recursos de validação, etc.
formReducer
Reducer da biblioteca Redux-Forms que irá modificar a store sempre que um evento (action) de formulário for disparado
reduxForm()
Habilita o componente a utilizar a biblioteca Redux-Form
<Field/>
Componente que será utilizado para desenvolver os campos do formulário.
Modificando o valor da store através dos reducers:
Acessando dados de uma API no Redux:
Redux-saga é uma biblioteca que foca em fazer os efeitos colaterais (ex: chamadas assíncronas para buscar dados em uma API, acessar o cache do navegador, etc) em aplicações React/Redux serem mais fáceis e simples de se criar e manter.
Redux Saga expõe vários métodos chamados de Effects, e vamos usar vários deles:
Metodos | Descrição |
---|---|
fork(), | realiza uma operação não bloqueante com a função passada |
take(), | pausa as operações até receber uma redux action |
race(), | executa Effects simultaneamente, e cancela todos quando um efeito retorna seu resultado |
call(), | executa uma função. Se essa função retornar uma Promise, ele irá pausar a Saga até a Promise ser resolvida |
put(), | despacha uma redux action |
select(), | executa uma função seletora que irá buscar dados do estado global do Redux |
takeLatest(), | irá executar as operações recebidas, porém, irá retornar apenas o valor da última. Se a mesma operação for enviada mais de uma vez, elas serão ignoradas, exceto a última (ex: click -> loadUser, usuário clica 4 vezes no botão (ele é legal né, quer testar sua app), apenas a função enviada no último click será executada/retornado o valor, as outras serão ignoradas) |
takeEvery(), | irá retornar os valores de todas as operações recebidas |
JEST (https://jestjs.io/docs/en/tutorial-react)
ENZYME (https://airbnb.io/enzyme/)
prop-types (https://fettblog.eu/typescript-react/prop-types/)
Publicando o projeto (Build)
npm install -g surge
Gerando o build do projeto:
npm run build
Instalando o servidor local para executar o build:
npm install -g serve
serve -s build
Publicando no servidor surge
cd build
surge
.
.
.
No ecossistema ReactJS, algumas das bibliotecas de estilos mais utilizadas são:
Styled-components: Esta é uma biblioteca muito popular para estilizar componentes React usando CSS-in-JS. Ela permite escrever estilos CSS diretamente no JavaScript, o que facilita o encapsulamento de estilos junto com a lógica dos componentes. É amplamente adotada pela sua facilidade de uso e flexibilidade.
Material-UI: Baseado no design de materiais do Google, o Material-UI é uma biblioteca de componentes React que oferece uma variedade de elementos de interface de usuário estilizados, como botões, cards, barras de navegação, entre outros. É uma escolha popular devido à sua extensa documentação e à vasta coleção de componentes prontos para uso.
Ant Design: Desenvolvido pela equipe da Ant Financial (Alibaba), o Ant Design é uma biblioteca de componentes React com um conjunto rico de elementos de interface de usuário, seguindo os padrões de design da Ant Financial. É muito utilizado em aplicações empresariais e possui uma ampla gama de componentes customizáveis.
Bootstrap: Embora seja mais conhecido por sua integração com o jQuery, o Bootstrap também oferece uma versão específica para React chamada React-Bootstrap. Ele fornece componentes React que seguem as diretrizes visuais e de interação do Bootstrap, facilitando a criação de layouts responsivos e modernos.
Chakra UI: Esta é uma biblioteca relativamente nova, mas ganhando rapidamente popularidade devido à sua ênfase na acessibilidade, responsividade e facilidade de uso. Chakra UI oferece uma variedade de componentes estilizados e temas customizáveis para criar interfaces consistentes e acessíveis.
.
.
.
Os frameworks mais utilizados para testes no ecossistema React e no desenvolvimento de aplicações web em geral incluem:
Jest: O Jest é um dos frameworks de teste mais populares para JavaScript. Ele é amplamente utilizado para testes unitários, testes de integração e testes de snapshot em aplicações React. O Jest é conhecido pela sua simplicidade de uso, configuração fácil e suporte a recursos avançados como mocks e spies.
React Testing Library: Este não é exatamente um framework de teste, mas uma biblioteca de utilitários para testar componentes React. Ela é projetada para promover boas práticas de testes e interações de usuário realistas. A React Testing Library é comumente usada em conjunto com o Jest para testes de componentes React.
Enzyme: O Enzyme é outra biblioteca popular para testes de componentes React. Ele fornece utilitários para manipular, simular eventos e testar componentes de forma isolada. Embora o Enzyme seja amplamente utilizado, o time do React recomenda o uso da React Testing Library para novos projetos.
Cypress: O Cypress é uma ferramenta de teste end-to-end (E2E) que permite testar aplicações web em um ambiente de navegador real. Ele é usado para testes de integração e testes de ponta a ponta, simulando interações do usuário e verificando o comportamento da aplicação em um ambiente real.
Performance Testing Frameworks:
.
.
.
npm install -g create-react-app
npx create-react-app nome_do_projeto
npm start
create-react-app --version
meu-projeto/
├── public/
│ ├── index.html
│ └── ...
├── src/
│ ├── assets/
│ │ └── imagens/
│ │ └── estilos/
│ │ └── estilos.css
│ ├── components/
│ │ ├── FormularioUsuarios.js
│ │ └── ListaUsuarios.js
│ ├── models/
│ │ └── Usuario.js
│ ├── services/
│ │ └── UsuarioService.js
│ ├── App.js
│ └── index.js
├── node_modules/
├── package.json
└── README.md
.
.
.
package.json
{
"name": "projeto",
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts 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"
]
}
}
App.js
import './App.css';
import React, { useState } from 'react';
const style = {
table: {
borderCollapse: 'collapse'
},
tableCell: {
border: '1px solid gray',
margin: 0,
padding: '5px 10px',
width: 'max-content',
minWidth: '150px'
},
form: {
container: {
padding: '20px',
border: '1px solid #F0F8FF',
borderRadius: '15px',
width: 'max-content',
marginBottom: '40px'
},
inputs: {
marginBottom: '5px'
},
submitBtn: {
marginTop: '10px',
padding: '10px 15px',
border: 'none',
backgroundColor: 'lightseagreen',
fontSize: '14px',
borderRadius: '5px'
}
}
}
function UsuariosForm({ addUsuarios }) {
const [nome, setNome] = useState("");
const [email, setEmail] = useState("");
const [celular, setCelular] = useState("")
const handleSubmit = (e) => {
e.preventDefault();
addUsuarios({ nome, email, celular });
setNome('');
setEmail('');
setCelular('');
}
return (
<form onSubmit={handleSubmit} style={style.form.container}>
<label>Nome:</label>
<br />
<input
style={style.form.inputs}
className='nome'
name='nome'
type='text'
value={nome}
onChange={(e) => setNome(e.target.value)}
/>
<br />
<label>E-mail:</label>
<br />
<input
style={style.form.inputs}
className='email'
name='email'
type='text'
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<br />
<label>Celular:</label>
<br />
<input
style={style.form.inputs}
className='celular'
name='celular'
type='text'
value={celular}
onChange={(e) => setCelular(e.target.value)}
/>
<br />
<input
style={style.form.submitBtn}
className='submitButton'
type='submit'
value='Adicionar'
/>
</form>
)
}
function ListaTable({ addUsuarios }) {
return (
<table style={style.table} className='listaTable'>
<thead>
<tr>
<th style={style.tableCell}>Nome</th>
<th style={style.tableCell}>E-mail</th>
<th style={style.tableCell}>Celular</th>
</tr>
</thead>
<tbody>
{addUsuarios.map((entry, index) => (
<tr key={index}>
<td style={style.tableCell}>{entry.nome}</td>
<td style={style.tableCell}>{entry.email}</td>
<td style={style.tableCell}>{entry.celular}</td>
</tr>
))}
</tbody>
</table>
);
}
function App(props) {
const [usuario, setUsuarios] = useState([]);
const addUsuarios = (entry) => {
setUsuarios([...usuario, entry]);
};
return (
<section>
<UsuariosForm addUsuarios={addUsuarios} />
<ListaTable addUsuarios={usuario} />
</section>
);
}
export default App;
index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App1 from './App1';
import reportWebVitals from './reportWebVitals';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
reportWebVitals();
.
.
.
Instalar:
npm install jquery
npm install bootstrap
package.json
{
"name": "projeto",
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"bootstrap": "^5.3.3",
"jquery": "^3.7.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts 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"
]
}
}
App1.js
import './App1.css';
import React, { useState } from 'react';
// FORMULARIO
function UsuariosForm({ addUsuarios }) {
// SETA OS CAMPOS
const [nome, setNome] = useState("");
const [email, setEmail] = useState("");
const [celular, setCelular] = useState("");
const [foto, setFoto ] = useState("");
// CONSTRUTOR
const handleSubmit = (e) => {
e.preventDefault();
addUsuarios({ nome, email, celular, foto });
// LIMPA OS CAMPOS APOS ADICIONAR
setNome('');
setEmail('');
setCelular('');
setFoto('');
}
// DESIGN DO FORMULARIO
return (
<form onSubmit={handleSubmit} className="card col-md-6 offset-md-3 mt-5 shadow">
<div className='card-header text-center'>
<h2>Formulário de Cadastro</h2>
</div>
<div className='card-body'>
<div className="form-group">
<label>Nome:</label>
<input className="form-control" type="text" value={nome} onChange={(e) => setNome(e.target.value)} />
</div>
<div className="form-group">
<label>E-mail:</label>
<input className="form-control" type="text" value={email} onChange={(e) => setEmail(e.target.value)} />
</div>
<div className="form-group">
<label>Celular:</label>
<input className="form-control" type="text" value={celular} onChange={(e) => setCelular(e.target.value)} />
</div>
<div className="form-group">
<label>Foto:</label>
<input className="form-control" type="text" value={foto} onChange={(e) => setFoto(e.target.value)} />
</div>
<button className="btn btn-primary mt-3">Adicionar</button>
</div>
</form>
)
}
// LISTA RESGATA OS DADOS DO ADDUSUSARIOS DO CONSTRUTOR
function ListaTable({ addUsuarios }) {
return (
<table className='table table-bordered table-hover mt-5'>
<thead className='text-center text-uppercase'>
<tr>
<th>Foto</th>
<th>Nome</th>
<th>E-mail</th>
<th>Celular</th>
</tr>
</thead>
<tbody>
{addUsuarios.map((entry, index) => (
<tr key={index}>
<td><img src={entry.foto} className='img-thumbnail imagem-redimensionada img-responsive shadow'/></td>
<td>{entry.nome}</td>
<td>{entry.email}</td>
<td>{entry.celular}</td>
</tr>
))}
</tbody>
</table>
);
}
function App1() {
const [usuario, setUsuarios] = useState([]);
const addUsuarios = (entry) => {
setUsuarios([...usuario, entry]);
};
// CHAMA OS COMPONENTES
return (
<section className="container">
<UsuariosForm addUsuarios={addUsuarios} />
<ListaTable addUsuarios={usuario} />
</section>
);
}
export default App1;
App1.css
.imagem-redimensionada {
width: 100px ;
height: auto;
}
index.js
Anotar o Bootstrap e o Jquery
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App1 from './App1';
import reportWebVitals from './reportWebVitals';
import 'bootstrap/dist/css/bootstrap.min.css';
import 'jquery/dist/jquery.min.js';
import 'bootstrap/dist/js/bootstrap.bundle.min.js';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App1 />
</React.StrictMode>
);
reportWebVitals();