Essa abordagem tem seus pontos fortes. Se alguém se esforça para praticar imediatamente enquanto domina o React, só precisa consultar a documentação oficial e começar a trabalhar . Este material ( aqui , caso tenha interesse, sua versão em vídeo) foi escrito para quem deseja encontrar uma resposta para as seguintes perguntas: “Por que reagir? Por que o React funciona dessa maneira? Por que as APIs React são projetadas da maneira que são? "

Por que reagir?
A vida se torna mais fácil se os componentes desconhecem a comunicação da rede, a lógica de negócios do aplicativo ou seu estado. Esses componentes, recebendo os mesmos parâmetros de entrada, sempre formam os mesmos elementos visuais.
Quando a biblioteca React surgiu, ela mudou fundamentalmente a maneira como as bibliotecas e estruturas JavaScript funcionam. Enquanto outros projetos semelhantes promoveram as ideias de MVC, MVVM e similares, o React adotou uma abordagem diferente. Ou seja, aqui a renderização do componente visual do aplicativo foi isolada da apresentação do modelo. Graças ao React, uma arquitetura completamente nova apareceu no ecossistema do front-end JavaScript - Flux.
Por que a equipe React fez isso? Por que essa abordagem é melhor do que as anteriores, como a arquitetura MVC e o código espaguete escrito em jQuery? Se você estiver interessado nessas questões, pode assistir a esta palestra de 2013 sobre desenvolvimento de aplicativos JavaScript no Facebook.
Em 2013, o Facebook acaba de concluir um trabalho sério de integração em sua plataforma de chat. Esse novo recurso foi incorporado em quase todas as páginas do projeto, o chat influenciando os cenários usuais de trabalho com a plataforma. Era um aplicativo complexo embutido em outro aplicativo que não tinha sido fácil antes. A equipe do Facebook teve que lidar com tarefas não triviais, lidando com mutações DOM não controladas e a necessidade de fornecer experiência de usuário assíncrona paralela no novo ambiente.
Por exemplo, como saber com antecedência o que será exibido na tela em uma situação em que qualquer coisa, a qualquer momento e por qualquer motivo, pode acessar o DOM e fazer alterações nele? Como garantir que o que o usuário vê seja plotado corretamente?
Usando ferramentas de front-end populares que existiam antes do React, nada disso poderia ser garantido. Nos primeiros aplicativos da web, a "condição de corrida" no DOM era um dos problemas mais comuns.
Falta de determinismo = computação paralela + estado mutável.
Martin Oderski
A principal tarefa da equipe de desenvolvimento do React era resolver esse problema. Eles lidaram com isso com duas abordagens inovadoras principais:
- Vinculação de dados unidirecional usando a arquitetura Flux.
- Imutabilidade do estado do componente. Depois que o estado de um componente é definido, ele não pode mais ser alterado. As mudanças de estado não afetam os componentes renderizados. Em vez disso, essas mudanças levam à saída de uma nova visualização com um novo estado.
A maneira mais simples que encontramos de estruturar e renderizar componentes, de um ponto de vista conceitual, era simplesmente apontar para a mutação zero.
Tom Ochchino, JSConfUS 2013
A biblioteca React foi capaz de reduzir drasticamente o problema de mutações não controladas usando a arquitetura Flux. Em vez de anexar manipuladores de eventos para disparar atualizações de DOM para um número arbitrário de objetos arbitrários (modelos), a biblioteca React deu aos desenvolvedores uma maneira única de gerenciar o estado do componente. Este é o despacho de ações que afetam o data warehouse. Quando o estado da loja muda, o sistema solicita que o componente seja renderizado.

A arquitetura de fluxo
Quando me perguntam por que devo prestar atenção ao React, dou uma resposta simples: “A questão é que precisamos de renderização determinística de visualizações, e o React torna essa tarefa muito mais fácil”.
Observe que ler dados do DOM para implementar alguma lógica é um antipadrão. Quem quer que faça isso vai contra o propósito de usar o React. Em vez disso, os dados devem ser lidos do armazenamento e as decisões com base nesses dados devem ser tomadas antes que os componentes correspondentes sejam renderizados.
Se a renderização determinística de componentes fosse a única coisa sobre o React, então isso seria uma grande inovação. Mas a equipe de desenvolvimento do React não parou por aí. Esta equipe apresentou ao mundo uma biblioteca que possui outras características interessantes e exclusivas. E, conforme o projeto evoluiu, o React acrescentou coisas ainda mais úteis.
JSX
JSX é uma extensão JavaScript que permite criar componentes de interface do usuário declarativamente. JSX tem os seguintes recursos notáveis:
- Aplicação de marcação declarativa simples.
- O código de marcação está localizado no mesmo lugar que o código do componente.
- ( — ). , , ( — HTML, CSS, JavaScript).
- DOM.
- , React-. , React , ( , , React Native, , Netflix Gibbon, Canvas/WebGL-, react-html-email).
Se, antes do advento do JSX, era necessário descrever interfaces declarativamente, então era impossível fazer sem usar modelos HTML. Naquela época, não havia um padrão geralmente aceito para a criação de tais modelos. Cada estrutura usava sua própria sintaxe. Essa sintaxe precisava ser aprendida por alguém que, por exemplo, precisava percorrer alguns dados, incorporar valores de variáveis em um modelo de texto ou decidir qual componente de interface exibir e qual não.
Hoje em dia, se você olhar para diferentes ferramentas de front-end, verá que não
*ngFor
pode prescindir de uma sintaxe especial, como uma diretiva do Angular. Mas, uma vez que JSX pode ser chamado de superconjunto de JavaScript, a criação de marcação JSX pode tirar vantagem dos recursos JS existentes.
Por exemplo, você pode iterar em um conjunto de elementos usando o método
Array.prototype.map
. Você pode usar operadores lógicos, organizar renderização condicional usando o operador ternário. Você pode usar funções puras , pode construir strings usando literais de modelo . Em geral, todos os recursos de JavaScript estão disponíveis para aqueles que descrevem interfaces em JSX. Acho que essa é uma grande vantagem do React em relação a outros frameworks e bibliotecas.
Aqui está um exemplo de código JSX:
const ItemList = ({ items }) => (
<ul>
{items.map((item) => (
<li key={item.id}>
<div>{item.name}</div>
</li>
))}
</ul>
);
É verdade que, ao trabalhar com JSX, você precisa levar em consideração alguns recursos que, a princípio, podem parecer incomuns.
- , , HTML. ,
class
className
. camelCase. - , , , JSX-
key
. .id
,key
.
O React não impõe ao desenvolvedor a única maneira correta de trabalhar com CSS. Por exemplo, você pode passar um objeto JavaScript com estilos para um componente, gravando-o em uma propriedade
style
. Com essa abordagem, a maioria dos nomes de estilo familiares serão substituídos por seus equivalentes camelCase. Mas as possibilidades de trabalhar com estilos não se limitam a isso. Na prática, eu uso simultaneamente diferentes abordagens para estilizar aplicativos React. A abordagem escolhida depende do estilo que você deseja. Por exemplo, eu uso estilos globais para estilizar temas de aplicativos e layouts de página, e estilos locais para personalizar a aparência de um componente específico.
Aqui estão meus recursos de estilo favoritos do React:
- CSS-, . , . — , .
- CSS- — CSS- . JavaScript-. CSS-, . Next.js, , .
- O pacote styled-jsx , que permite declarar estilos diretamente no código do componente React. Isso é semelhante a usar uma tag
<style>
em HTML. O escopo de tais estilos pode ser chamado de "hiperlocal". A questão é que os estilos afetam apenas os elementos aos quais são aplicados e seus filhos. Ao usar Next.js, o pacote styled-jsx pode ser usado sem a necessidade de se conectar e configurar algo você mesmo.
Eventos sintéticos
O React nos fornece um wrapper para vários navegadores
SyntheticEvents
que representa eventos sintéticos e é projetado para unificar o trabalho com eventos DOM. Os eventos sintéticos são muito úteis por vários motivos:
- , . .
- . , , , JavaScript HTML, . . , , React- .
- . . , , . , , , . . , . , JavaScript, .
Observe que as propriedades de um evento sintético não podem ser acessadas de uma função assíncrona devido ao pool de eventos. Para implementar esse esquema de trabalho, você precisa pegar dados do objeto de evento e gravá-los em uma variável acessível à função assíncrona.
Ciclo de vida do componente
O conceito de ciclo de vida dos componentes React concentra-se na proteção do estado do componente. O estado do componente não deve mudar enquanto está sendo exibido. Isso é alcançado devido ao seguinte esquema de trabalho: o componente está em um determinado estado e renderizado. Então, graças aos eventos do ciclo de vida, torna-se possível aplicar efeitos a ele, você pode influenciar seu estado, trabalhar com eventos.
Entender o ciclo de vida dos componentes do React é extremamente importante para desenvolver interfaces e ao mesmo tempo não brigar com o React, mas usar esta biblioteca como pretendido por seus desenvolvedores. "Batalhas" com o React, como alterar incorretamente o estado dos componentes ou ler dados do DOM, anulam os pontos fortes desta biblioteca.
No React, a partir da versão 0.14, havia uma sintaxe de descrição de componente baseada em classe que permite manipular eventos de ciclo de vida do componente. Existem três estágios críticos no ciclo de vida dos componentes do React: Montar, Atualizar e Desmontar.

Ciclo de vida do componente
O estágio de atualização pode ser dividido em três partes: Render (renderização), Precommit (preparação para fazer alterações na árvore DOM), Commit (fazer alterações na árvore DOM).

A estrutura do estágio de atualização
Detenhamo-nos nestes estágios do ciclo de vida do componente com mais detalhes:
- Render — .
render()
, . , JSX. - Precommit — DOM,
getSnapShotBeforeUpdate
. , , . - Commit - durante esta fase do ciclo de vida do componente, o React atualiza o DOM e as referências . Aqui você pode usar um método
componentDidUpdate
ou ganchouseEffect
. É aqui que você pode executar efeitos, agendar atualizações, usar o DOM e outras tarefas semelhantes.
Dan Abramov preparou um diagrama excelente que ilustra como funcionam os mecanismos do ciclo de vida dos componentes.

O ciclo de vida dos componentes do React
Acho que representar os componentes como classes de longa duração não é o melhor modelo mental do React. Lembre-se de que o estado dos componentes do React não deve sofrer mutação. O estado obsoleto deve ser substituído por um novo. Cada substituição faz com que o componente seja renderizado novamente. Isso dá ao React o que é indiscutivelmente seu recurso mais importante e mais valioso: suporte para uma abordagem determinística para renderizar componentes visuais.
Esse comportamento é mais bem pensado assim: toda vez que o componente é renderizado, a biblioteca chama uma função determinística que retorna JSX. Esta função não deve invocar seus próprios efeitos colaterais. Mas ela, se precisar, pode passar pedidos ao React para realizar tais efeitos.
Em outras palavras, faz sentido pensar na maioria dos componentes React como funções puras que recebem parâmetros de entrada e retornam JSX. As funções puras têm os seguintes recursos:
- Quando recebem a mesma entrada, eles sempre retornam a mesma saída (eles são determinísticos).
- Eles não têm efeitos colaterais (ou seja, não funcionam com recursos de rede, não enviam nada para o console, não gravam nada
localStorage
e assim por diante).
Observe que, se os efeitos colaterais forem necessários para que um componente funcione, você pode executá-los usando
useEffect
ou referindo-se ao criador da ação passado ao componente por meio dos parâmetros de entrada e permitindo que os efeitos colaterais sejam tratados fora do componente .
React Hooks
O React 16.8 apresenta um novo conceito chamado ganchos React. Essas são funções que permitem que você se conecte aos eventos do ciclo de vida do componente sem depender da sintaxe da classe ou dos métodos do ciclo de vida do componente. Como resultado, tornou-se possível criar componentes não na forma de classes, mas na forma de funções.
Chamar um gancho, em geral, significa um efeito colateral - que permite que o componente trabalhe com seu estado e com o subsistema de E / S. Um efeito colateral é qualquer mudança no estado visível fora da função, exceto por uma mudança no valor retornado pela função.
Hook useEffectPermite enfileirar os efeitos colaterais para execução posterior. Eles serão chamados no momento apropriado no ciclo de vida do componente. Esse momento pode vir imediatamente após o componente ser montado (por exemplo, quando o método de ciclo de vida componentDidMount é chamado ), durante a fase de confirmação (método componentDidUpdate ), logo antes de o componente ser desmontado ( componentWillUnmount ).
Observe que existem três métodos de ciclo de vida de componentes associados a um gancho? O ponto aqui é que os ganchos permitem combinar lógica relacionada, e não "configurá-la", como era antes deles, de acordo com métodos diferentes do ciclo de vida do componente.
Muitos componentes precisam realizar alguma ação enquanto estão sendo montados, algo precisa ser atualizado toda vez que o componente é redesenhado, recursos precisam ser liberados imediatamente antes de desmontar o componente para evitar vazamentos de memória. Graças ao uso,
useEffect
todas essas tarefas podem ser resolvidas em uma função, sem dividir sua solução em 3 métodos diferentes, sem misturar seu código com o código de outras tarefas que não estão relacionadas a elas, mas também precisam desses métodos.
Aqui está o que os ganchos do React nos oferecem:
- Eles permitem que você crie componentes que são representados como funções em vez de classes.
- Eles ajudam você a organizar melhor seu código.
- Eles tornam mais fácil compartilhar a mesma lógica entre diferentes componentes.
- Novos ganchos podem ser criados compondo ganchos existentes (chamando-os de outros ganchos).
Em geral, recomendamos o uso de componentes funcionais e ganchos em vez de componentes baseados em classe. Os componentes funcionais são geralmente mais compactos do que os componentes baseados em classe. Seu código é melhor organizado, mais legível, mais reutilizável e mais fácil de testar.
Componentes do recipiente e componentes de apresentação
Em um esforço para melhorar a modularidade dos componentes e sua reutilização, foco no desenvolvimento de dois tipos de componentes:
- Os componentes do contêiner são componentes que estão conectados a fontes de dados e podem ter efeitos colaterais.
- Os beans de apresentação são, em sua maioria, beans puros que, dados os mesmos adereços e contexto, sempre retornam o mesmo JSX.
Os componentes puros não devem ser confundidos com a classe base React.PureComponent , que tem esse nome porque não é seguro usá-la para criar componentes que não sejam puros.
▍ Componentes de apresentação
Considere os recursos dos componentes de apresentação:
- Eles não interagem com os recursos da rede.
- Eles não salvam dados
localStorage
ou carregam de lá. - Eles não fornecem alguns dados imprevisíveis.
- Eles não se referem diretamente à hora atual do sistema (por exemplo, chamando um método
Date.now()
). - Eles não interagem diretamente com o armazenamento de estado do aplicativo.
- - , , , .
É por causa do último item da lista que mencionei, ao falar sobre os componentes da apresentação, que esses são na maioria componentes puros. Esses componentes lêem seu estado a partir do estado global do React. Portanto, como os ganchos
useState
e useReducer
fornecê-los com alguns dados implícitos (ou seja - dados que não estão descritos na função de assinatura) que, do ponto de vista técnico, não pode chamar tais componentes são "limpos". Se você precisa que eles estejam realmente limpos, você pode delegar todas as tarefas de gerenciamento de estado ao componente do contêiner, mas suponho que você não deva fazer isso, pelo menos até que o funcionamento correto do componente possa ser verificado usando testes.
Melhor o inimigo do bom.
Voltaire
▍ Componentes do recipiente
Os componentes do contêiner são aqueles responsáveis por gerenciar o estado, executar operações de E / S ou qualquer outra tarefa que possa ser um efeito colateral. Eles não precisam renderizar nenhuma marcação por conta própria. Em vez disso, eles delegam a tarefa de renderização aos componentes da apresentação e eles próprios servem como um invólucro para esses componentes. Normalmente, um componente de contêiner em um aplicativo React + Redux simplesmente chama
mapStateToProps()
e mapDispatchToProps()
então passa os dados apropriados para os componentes de apresentação. Os contêineres também podem ser usados para algumas tarefas gerais, que discutiremos a seguir.
Componentes de ordem superior
Um Componente de Ordem Superior (HOC) é um componente que pega outros componentes e retorna um novo componente que implementa uma nova funcionalidade com base nos componentes originais.
Os componentes de ordem superior funcionam envolvendo alguns componentes com outros. Um componente wrapper pode implementar alguma lógica e criar elementos DOM. Ele pode ou não passar acessórios adicionais para o componente embalado.
Ao contrário dos ganchos React e adereços de renderização, os componentes de ordem superior se prestam à composição usando a abordagem padrão para a composição de funções. Isso permite que você descreva declarativamente os resultados da composição de recursos destinados ao uso em diferentes locais do aplicativo. Ao mesmo tempo, os componentes prontos não devem estar cientes da existência de certas possibilidades. Aqui está um exemplo de HOC de EricElliottJS.com :
import { compose } from 'lodash/fp';
import withFeatures from './with-features';
import withEnv from './with-env';
import withLoader from './with-loader';
import withCoupon from './with-coupon';
import withLayout from './with-layout';
import withAuth from './with-auth';
import { withRouter } from 'next/router';
import withMagicLink from '../features/ethereum-authentication/with-magic-link';
export default compose(
withEnv,
withAuth,
withLoader,
withLayout({ showFooter: true }),
withFeatures,
withRouter,
withCoupon,
withMagicLink,
);
É mostrado aqui uma mistura de muitos recursos compartilhados por todas as páginas do site. Ou seja, ele
withEnv
lê as configurações das variáveis de ambiente, withAuth
implementa o mecanismo de autenticação GitHub, withLoader
mostra uma animação ao carregar os dados do usuário, , withLayout({ showFooter: true })
exibe um layout padrão com um rodapé, withFeature
mostra as configurações, withRouter
carrega o roteador, withCoupon
é responsável por trabalhar com cupons e withMagicLing
oferece suporte à autenticação do usuário sem uma senha usando Magic .
A propósito, como a autenticação por senha está desatualizada e é uma prática perigosa, vale a pena usar outros métodos de autenticação de usuário atualmente.
Quase todas as páginas do site mencionado tiram proveito de todos esses recursos. Considerando que são compostos por meio de um componente de ordem superior, pode-se incluí-los todos em um componente container com apenas uma linha de código. Por exemplo, esta seria a aparência da página do tutorial:
import LessonPage from '../features/lesson-pages/lesson-page.js';
import pageHOC from '../hocs/page-hoc.js';
export default pageHOC(LessonPage);
Esses componentes de ordem superior têm uma alternativa, mas essa é uma construção duvidosa chamada de "pirâmide da desgraça" e é melhor não usá-la. Isto é o que parece:
import FeatureProvider from '../providers/feature-provider';
import EnvProvider from '../providers/env-provider';
import LoaderProvider from '../providers/loader-provider';
import CouponProvider from '../providers/coupon-provider';
import LayoutProvider from '../providers/layout-provider';
import AuthProvider from '../providers/auth-provider';
import RouterProvider from '../providers/RouterProvider';
import MagicLinkProvider from '../providers/magic-link-provider';
import PageComponent from './page-container';
const WrappedComponent = (...props) => (
<EnvProvider { ...props }>
<AuthProvider>
<LoaderProvider>
<LayoutProvider showFooter={ true }>
<FeatureProvider>
<RouterProvider>
<CouponProvider>
<MagicLinkProvider>
<YourPageComponent />
</MagicLinkProvider>
</CouponProvider>
</RouterProvider>
</FeatureProvider>
</LayoutProvider>
</LoaderProvider>
</AuthProvider>
</EnvProvider>
);
E isso terá que ser repetido em todas as páginas. E se algo precisa ser mudado nesta estrutura, então mudanças terão que ser feitas onde quer que esteja presente. Acho que as desvantagens dessa abordagem são bastante óbvias.
Usar composição para resolver problemas gerais é uma das melhores maneiras de reduzir a complexidade do código do seu aplicativo. A composição é tão importante que até escrevi um livro sobre isso .
Resultado
- Por que reagir? O React nos dá uma renderização determinística das representações visuais dos componentes, que se baseia na vinculação de dados unidirecional e no estado imutável dos componentes.
- JSX nos permite descrever facilmente interfaces declarativamente em código JavaScript.
- - .
- . , . , DOM DOM.
- React , . , , .
- - . - .
- , . ( , ).
?
Neste artigo do React, cobrimos muitos conceitos de programação funcional. Se você está se esforçando para um entendimento profundo dos princípios de desenvolvimento de aplicativos React, será útil atualizar seus conhecimentos sobre funções puras , sobre imutabilidade , sobre currying e aplicação parcial de funções, sobre composição de funções. Você pode encontrar materiais relacionados em EricElliottJS.com .
Eu recomendo usar React em conjunto com Redux , Redux-Saga e RITEway . Redux é recomendado para uso com Autodux e Immer... Você pode tentar usar Redux-DSM para organizar fluxos de trabalho de estado complexo .
Quando você entender o básico e estiver pronto para construir aplicativos React reais, dê uma olhada em Next.js e Vercel . Essas ferramentas ajudarão a automatizar a configuração do sistema de construção do projeto e do pipeline de CI / CD, com a ajuda delas, você pode preparar o projeto para uma implantação otimizada no servidor. Eles têm o mesmo efeito que uma equipe DevOps inteira, mas são totalmente gratuitos.
Quais ferramentas auxiliares você usa ao desenvolver aplicativos React?

