Sempre que você cria um projeto React, uma das primeiras coisas que você precisa instalar junto com o pacote react é o pacote react-dom. Você já se perguntou por que precisa disso?
Pode ser uma surpresa, mas não podemos renderizar os componentes da IU apenas com o pacote react. Para renderizar a IU para o navegador, temos que usar o react-dom. Neste guia, exploraremos o gerenciamento de componentes DOM com ReactDOM criando um aplicativo de amostra. Conforme você prossegue, faremos algumas alterações em nosso código para aprender sobre os vários métodos disponíveis para você.
Você pode verificar código para o aplicativo de amostra no Github e o implementado site .
ReactDOM
O ReactDOM renderiza componentes ou elementos JSX para o DOM. O objeto ReactDOM possui apenas alguns métodos; você provavelmente já usou o método render (), que é responsável por renderizar o aplicativo no navegador.
O pacote react-dom serve como ponto de entrada para o DOM. Nós o importamos no início de nosso projeto assim:
import ReactDOM de’react-dom’;
Antes de entrar nos detalhes dos métodos do ReactDOM, vamos primeiro entender por que precisamos do ReactDOM em vez de apenas usar o DOM.
Virtual DOM (VDOM) vs DOM
JavaScript e O HTML não pode se comunicar diretamente um com o outro, então o DOM foi desenvolvido para lidar com esse problema. Quando você abre uma página da web, o mecanismo do navegador traduz todo o seu conteúdo em um formato que o JavaScript pode entender-uma árvore DOM.
A estrutura dessa árvore é idêntica à do documento HTML correspondente. Se um elemento estiver aninhado dentro de outro no código HTML, isso será refletido na árvore DOM.
Você pode ver por si mesmo como é o DOM abrindo a guia Elementos no painel de ferramentas do desenvolvedor do seu navegador. O que você verá será muito semelhante ao código HTML, exceto que, em vez de olhar para as tags HTML, o que você realmente está vendo são os elementos da árvore DOM.
O DOM é a representação lógica de um página da web criada e armazenada no navegador do usuário. O navegador pega o HTML do site e o transforma em um DOM e, em seguida, pinta o DOM na tela do usuário, tornando o site visível para o usuário.
Vamos ver o DOM em ação. O diagrama mostra como o DOM vê o HTML:
Virtual DOM vs DOM
O DOM tem alguns problemas, no entanto. Imagine que o usuário clica em um botão para remover um item. Esse nó e todos os outros nós que dependem dele serão removidos do DOM.
Sempre que um navegador detecta uma alteração no DOM, ele repinta a página inteira usando a nova versão. Mas realmente precisamos redesenhar a página inteira? Comparar dois DOMs para determinar quais partes foram alteradas consome muito tempo.
Como resultado, é realmente mais rápido para os navegadores simplesmente redesenhar a página inteira sempre que um usuário interage com o site. É aí que entra o Virtual DOM.
Um Virtual DOM é quando o React cria sua própria representação do DOM como um objeto JavaScript. Sempre que uma alteração é feita no DOM, a biblioteca, em vez disso, faz uma cópia desse objeto JavaScript, faz a alteração nessa cópia e compara os dois objetos JavaScript para ver o que mudou. Em seguida, ele informa o navegador sobre essas alterações e apenas essas partes do DOM são repintadas.
Fazer alterações em objetos JavaScript e compará-los é muito mais rápido do que tentar fazer o mesmo com DOMs. Uma vez que esta cópia do DOM é armazenada na memória como um objeto JavaScript, ela é chamada de Virtual DOM.
O Virtual DOM evita repinturas desnecessárias repintando apenas elementos e grupos atualizados. O VDOM é uma representação leve e rápida na memória do DOM real.
Embora o React funcione com o VDOM sempre que possível, ele ainda interagirá regularmente com o DOM real. O processo pelo qual o React atualiza o DOM real para ser consistente com o VDOM é chamado de reconciliação .
ReactDOM.render ()
Agora que temos um melhor entendimento do DOM e VDOM, podemos começar a aprender sobre nosso primeiro método: ReactDOM.render. O uso do método render é o seguinte:
ReactDOM.render (element, container [, callback]) ReactDOM.render (
ReactDOM
, document.getElementById (“app”))
O primeiro argumento é o elemento ou componente que queremos renderizar, e o segundo argumento é o elemento HTML (o nó de destino) ao qual queremos anexá-lo.
Geralmente, quando criamos nosso projeto com create-react-app, ele nos dá um div com o id de uma raiz dentro de index.html, e encapsulamos nosso aplicativo React dentro dessa div raiz.
Então, quando usamos o ReactDOM.render () método, passamos nosso componente para o primeiro argumento e nos referimos a id=”root”com document.getElementById (“root”) como o segundo argumento:
//src/index.js import React from’react’; importar ReactDOM de’react-dom’;//criar o componente do aplicativo const App=()=> {return
}//renderizar o componente do aplicativo e mostrá-lo na tela ReactDOM.render (
Goodbye ReactDOM.render ()
Em junho, a equipe React anunciou React 18 , e com a nova atualização, não usaremos mais ReactDOM.render (). Em vez disso, usaremos ReactDOM.createRoot.
A versão alfa do React 18 está disponível, mas levará vários meses para o beta público. Se você quiser experimentar a versão do React 18 alpha, instale-o assim:
npm install react @ alpha react-dom @ alpha
Com o React 18, usaremos ReactDOM.createRoot para criar uma raiz, e em seguida, passe a raiz para a função de renderização. Ao alternar para createRoot, você obterá todos os novos recursos do React 18 por padrão:
import ReactDOM de”react-dom”; importar App de”App”; const container=document.getElementById (“app”); const root=ReactDOM.createRoot (contêiner); root.render (
ReactDOM.createPortal ()
Nosso segundo método no ReactDOM é createPortal.
Você já precisou criar uma sobreposição ou modal? O React tem diferentes funções para lidar com modais, dicas de ferramentas ou outros recursos dessa natureza. Uma é a função ReactDOM.createPortal ().
Para renderizar um modal, ou sobreposição, precisamos usar a propriedade z-index para gerenciar a ordem em que os elementos aparecem na tela. O z-index nos permite posicionar os elementos em termos de profundidade, ao longo do eixo z.
No entanto, como você sabe, só podemos renderizar um div, com todos os outros elementos aninhados dentro de nosso div raiz. Com a ajuda da função createPortal, podemos renderizar nossos modais fora da árvore de componentes principal. O modal será filho do elemento body. Vamos ver como.
Em nosso index.html adicionaremos outro div para o modal:
//index.html
A função ReactDOM.createPortal () leva dois argumentos: o primeiro é JSX , ou o que queremos renderizar na tela, e o segundo argumento é uma referência ao elemento que queremos anexar ao nosso modal:
//Modal.js import {createPortal} from’react-dom’; const modalRoot=document.querySelector (‘# modal’); const Modal=({filhos})=> createPortal (filhos, modalRoot); exportar Modal padrão;
Agora, para renderizar nosso componente, podemos passar o que quisermos mostrar entre as tags de abertura e fechamento de nosso componente modal. Isso será renderizado dentro do componente modal como filhos. Eu renderizei o modal dentro de App.js.
Em nosso arquivo App.js, temos um botão para abrir o modal. Quando o usuário interage com o botão, mostramos o modal junto com um botão Fechar:
//App.js import React, {useCallback, useState} from’react’; importar Modal de’../Modal’; const App=()=> {const [showModal, setShowModal]=useState (false); const openModal=useCallback (()=> setShowModal (true), []); const closeModal=useCallback (()=> setShowModal (false), []); return (
Sou um modal!
); }; exportar aplicativo padrão;
ReactDOM.unmountComponentAtNode ()
Usamos esse método quando precisamos remover um nó DOM depois de montado e limpar seus manipuladores de evento e estado.
Continuaremos com nosso código novamente, desta vez vamos desmontar nossa div raiz:
ReactDOM.unmountComponentAtNode (container)
Para o contêiner, estamos passando a div raiz, então quando o usuário clicar no botão, ele irá desmontar o aplicativo.
Se você tentar desmontar o id modal, verá um erro. Isso ocorre porque o modal não está montado, então ele retornará falso:
//App.js const App=()=> {ReactDOM.unmountComponentAtNode (document.getElementById (“root”)); return ()}
Este código é suficiente para desmontar a raiz.
ReactDOM.findDOMNode ( )
Sabemos que podemos renderizar nossos elementos DOM com o método render. Também podemos obter acesso ao nó DOM subjacente com a ajuda do método findDOMNode. De acordo com a documentação do React, este método é desencorajado porque atravessa a abstração do componente.
NOTA: o método findDOMNode foi descontinuado no StrictMode.
Geralmente, se você precisar se referir a qualquer elemento DOM, é aconselhável usar o gancho useRef . Na maioria dos casos, você pode anexar um ref ao nó DOM e evitar o uso de findDOMNode.
Outro ponto-chave é o elemento Node que você deseja acessar deve ser montado, o que significa que deve estar no DOM. Se não estiver montado, findDOMNode retorna nulo. Depois de obter acesso ao nó DOM montado, você pode usar a API DOM familiar para inspecionar o nó.
findDOMNode leva um parâmetro e é o componente:
ReactDOM.findDOMNode (componente)
Continuaremos com o código que usamos no método createPortal. Eu criei um novo botão e adicionei o texto Find The Modal Button e mude sua cor de fundo, e adicionei uma função de manipulador onClick. Com esta função, acessei seu className com o método document.querySelector e alterei sua cor de fundo para preto:
const App=()=> {const handleFindDOMNode=()=> {const node=document.querySelector (‘.nó’); ReactDOM.findDOMNode (nó).style.backgroundColor=’black’; }; return ()}
ReactDOM.hydrate () e renderização do lado do servidor (SSR)
O método hydrate nos ajudará a pré-renderizar tudo no lado do servidor e, em seguida, enviar ao usuário a marcação completa. É usado para adicionar conteúdo a um contêiner que foi renderizado pelo ReactDOMServer.
Isso pode soar como um jargão agora, mas a principal lição é que podemos renderizar nossos aplicativos React no cliente ou no servidor. Aqui está uma rápida visão geral das principais diferenças entre a Renderização do Lado do Cliente (CSR) e a Renderização do Lado do Servidor (SSR).
Renderização do Lado do Cliente (CSR)
Quando criamos e execute nosso projeto com create-react-app, ele não mostra o conteúdo da página:
Como você pode ver na captura de tela, temos apenas nossos divs e uma referência aos nossos Pacote de JavaScript, nada mais. Portanto, esta é na verdade uma página em branco. Isso significa que, quando carregamos nossa página pela primeira vez, o servidor faz uma solicitação ao HTML, CSS e JavaScript. Após a renderização inicial, o servidor verifica nosso JavaScript agrupado (ou código React, em nosso caso) e pinta a IU. Esta abordagem tem alguns prós e contras.
Prós:
Implementação rápida estática oferece suporte a aplicativos de página única (SPA)
Contras:
Renderiza uma página em branco no carregamento inicial Tamanho do pacote pode ser grande Não é bom para SEO
Renderização do lado do servidor (SSR)
Com a renderização do lado do servidor, não renderizamos mais uma página vazia. Com essa abordagem, o servidor cria arquivos HTML estáticos que o navegador renderiza.
É assim que o SSR funciona: quando o usuário solicita um site, o servidor renderiza a versão estática do aplicativo, permitindo que os usuários vejam o o site é carregado. O site ainda não é interativo, portanto, quando o usuário interage com o aplicativo, o servidor baixa o JavaScript e o executa.
O site torna-se responsivo substituindo o conteúdo estático pelo conteúdo dinâmico. A função ReactDOM.hydrate () é realmente chamada no evento de carregamento desses scripts e conecta a funcionalidade com a marcação renderizada.
Se você estiver curioso, quando criamos nosso projeto com SSR, podemos ver o HTML e código JavaScript renderizado no carregamento inicial:
Prós:
Melhor desempenho Ótimo para SEO para nos ajudar a criar sites facilmente indexáveis e rastreáveis Interatividade rápida Acelera o tempo de upload executando React no servidor antes de servir a solicitação ao usuário.
Contras:
Cria muitas solicitações de servidor se você tiver muitos elementos interativos em seu site, isso pode tornar a renderização
Demo de ReactDOM.hydrate ()
Como você pode imagine, para que isso funcione, precisamos criar um servidor. Estaremos criando o servidor com Express, mas primeiro precisamos fazer uma limpeza.
Para executar um servidor Node.js usando hydrate, precisamos remover todas as referências à janela e ao documento, porque iremos renderize nossa marcação no servidor, não no navegador.
Vamos para o arquivo Modal.js e mova o document.querySelector dentro do componente modal:
//Modal.js import {createPortal } de’react-dom’; let modalRoot; const Modal=({filhos})=> {modalRoot=modalRoot? modalRoot: document.querySelector (‘# modal’); retornar createPortal (filhos, modalRoot); }; exportar Modal padrão;
Em seguida, precisamos alterar ReactDOM.render para ReactDOM.hydrate dentro do arquivo src/index.js:
ReactDOM.hydrate (
Agora podemos criar nosso servidor. Crie uma nova pasta chamada server e crie um arquivo dentro desta pasta chamada server.js. Instale Express com npm install express:
//server/server.js import express express from’express’; importar fs de’fs’; importar caminho de’caminho’; import React from’react’; import {renderToString} de’react-dom/server’; importar App de’../src/App’; const app=express (); app.use (‘^/$’, (req, res, next)=> {fs.readFile (path.resolve (‘./build/index.html’),’utf-8′, (err, dados)=> {if (err) {console.error (err); return res.status (500).send (‘Error’);} return res.send (data.replace (‘
‘, `
`));});}); app.use (express.static (path.resolve (__ dirname,’..’,’build’))); app.listen (3000, ()=> {console.log (‘Ouvindo na porta 3000’);});
Aqui, exigimos Express, o módulo fs (sistema de arquivos), o caminho, React, ReactDOMServer.renderToString e App de nossa pasta src.
O ReactDOMServer.renderToString retorna a versão HTML estática de nosso aplicativo.
Em seguida, execute o comando build npm run build para criar uma pasta de construção. Configure o Babel e instale o npm i @ babel/preset-env @ babel/preset-react @ babel/register para ignorar estilos. Finalmente, crie um novo arquivo chamado server/index.js:
//server/index.js require (‘ignore-styles’); require (‘@ babel/register’) ({ignore: [/(node_modules)/], presets: [‘@ babel/preset-env’,’@ babel/preset-react’],}); requer (‘./servidor’);
Adicione um script para SSR em package.json:”ssr”:”node server/index.js”. Execute o servidor com npm run ssr.
Lembre-se, se você fizer alterações em seu aplicativo, primeiro execute npm run build e, em seguida, npm execute ssr.
Alterações para hidratar com React 18
No React 18, um novo SSR baseado em suspense arquitetura é introduzida . O método de hidrato também será substituído por hydrateRoot.
Conclusão
Nós cobrimos muito sobre ReactDOM. Para resumir, aqui estão as principais lições que aprendemos ao longo deste post:
React usa um DOM virtual, que nos ajuda a evitar repaint desnecessários de DOM e atualiza apenas o que mudou na IU. Usamos o método render para renderizar nossa IU componentes para o navegador, o método ReactDOM usado com mais frequência Usamos o método createRoot em vez do método render com React 18 Podemos criar modais e dicas de ferramentas com o método createPortal Podemos desmontar um componente com o método unmountComponentAtNode Podemos obter acesso a qualquer Nó DOM com o método findDOMNode, mas a melhor maneira é usar ref. Podemos usar SSR no React com a ajuda do método hidrato, basta estar preparado para React 18 e arquitetura SSR baseada em Suspense SSR nos ajuda a pré-renderizar tudo em o lado do servidor para uma melhor otimização de SEO