Skip to main content

A arte da renderização condicional: dicas e truques para desenvolvedores React e Next.js

Escrito por

Kumar Harsh

blog feature open source security

30 de outubro de 2023

0 minutos de leitura

Renderização condicional é uma técnica usada em aplicações web para renderizar seletivamente um componente entre várias opções, com base em uma condição, como o status de autenticação do usuário, suas permissões ou o estado da aplicação. Ela também pode ser usada para implementar vários conceitos fundamentais de UI do React, como roteamento no lado do cliente e carregamento preguiçoso.

Neste artigo, você vai conhecer os benefícios da renderização condicional, como ela difere do roteamento condicional e como implementar ambos em React, Next.js e Remix.

Benefícios da renderização condicional em React

Em aplicativos criados com React ou frameworks semelhantes, usar a renderização condicional traz diversos benefícios, incluindo tempos de carregamento menores.

O tempo de carregamento de uma aplicação web é influenciado pelo tamanho do Document Object Model (DOM) da página. Manter elementos demais — especialmente os que só são exibidos quando o usuário rola a página para baixo — pode resultar em um DOM desnecessariamente grande e reduzir o desempenho da sua aplicação.

Nessa situação, é possível usar o carregamento preguiçoso, uma técnica popular que adia o carregamento de recursos até que sejam necessários, para adiar a renderização de um componente até que o usuário role a página e ele entre na área visível. Uma das bibliotecas de carregamento preguiçoso mais populares para React, react-lazyload, usa a renderização condicional para renderizar componentes somente quando eles entram na área visível do navegador do usuário — ou seja, quando ficam visíveis para ele.

Além de melhorar o desempenho, a renderização condicional também pode aprimorar a experiência do usuário. Ela permite personalizar a interface de acordo com as características do usuário, como o estado de autenticação (isto é, exibir um botão de login para usuários não autenticados e um botão de logout para usuários autenticados no mesmo lugar da tela) e as permissões de acesso (isto é, exibir controles de edição e análises detalhadas para quem é dono do conteúdo, como publicações, e mostrar informações limitadas para os demais).

Além disso, a renderização condicional ajuda você a lidar com operações no lado do cliente, como a busca de dados e a comunicação com o backend. Você pode exibir condicionalmente uma barra de carregamento durante uma operação ou ocultar uma lista vazia enquanto os dados são carregados de uma fonte remota.

A renderização condicional também permite o roteamento no lado do cliente em aplicativos React de página única, como o pacote react-router.

Em resumo, é seguro dizer que a renderização condicional é uma das técnicas mais importantes usadas em React.

Renderização condicional vs. roteamento condicional

Ao falar de renderização condicional, muitas vezes surge o tema do roteamento condicional. Ele é semelhante à renderização condicional porque controla o que o usuário pode ver com base em condições como o estado do usuário ou da aplicação. No entanto, em vez de renderizar ou destruir componentes, ele leva o usuário de uma rota (ou página) a outra. Isso é útil para controlar o acesso.

Aplicações web podem ser acessadas diretamente por URLs. Isso significa que os usuários podem copiar e guardar o endereço de qualquer página do seu aplicativo, seja ela pública ou não. No caso de páginas privilegiadas (páginas não públicas acessíveis somente a usuários com determinadas funções, como páginas de perfil ou preferências pessoais), as URLs podem ser usadas indevidamente para tentar acessar conteúdo restrito.

Com o roteamento condicional, um aplicativo React pode verificar se uma solicitação recebida para renderizar uma página tem as permissões necessárias para acessar a rota. Se não tiver, a renderização é negada e a solicitação é redirecionada para outra página. Em geral, essa página pede que o usuário se autentique ou informa que o acesso foi negado.

Para ver o roteamento condicional em ação, tente acessar https://mail.google.com/mail em uma nova janela anônima. Você será redirecionado para a página de login do Google. Esse é o roteamento condicional funcionando nos bastidores.

No entanto, o roteamento condicional em uma SPA não garante a segurança. Mesmo antes de o seu aplicativo React de página única redirecionar usuários não autenticados, ele ainda contém o conteúdo da página privilegiada no código-fonte JavaScript. Isso pode levar a incidentes de acesso não autorizado a dados restritos. Por isso, é melhor configurar o roteamento condicional relacionado à autenticação no lado do servidor, usando frameworks como Next.js e Remix.

Como implementar a renderização condicional em React

Agora que você sabe mais sobre renderização condicional, na próxima seção vai aprender a implementá-la em um aplicativo React usando um dos conceitos fundamentais da programação: a instrução if…else.

Para começar, crie um novo aplicativo React executando os seguintes comandos:

npx create-react-app conditional-rendering-react
cd conditional-rendering-react
npm install

Quando o aplicativo estiver pronto, cole o código a seguir no arquivo src/App.js:

import { useState } from "react"

// Define two components
const LoginButton = (props) => {
  return <>
  <div>You are logged out</div>
  <div><button onClick={props.toggleLoggedIn}>Log In</button></div>
  </>
}

const LogoutButton = (props) => {
  return <>
  <div>You are now logged in</div>
  <div><button onClick={props.toggleLoggedIn}>Log Out</button></div>
  </>
}

function App() {
  // Define a state that the condition will be based upon
  const [loggedIn, setLoggedIn] = useState(false);

  // Define a function that can change the condition value
  const toggleLoggedIn = () => {
    setLoggedIn((currState) => {
        return !currState;
    })
  }

  // Use an if...else statement to render one out of two components based on the login state
  if (loggedIn)
    return <LogoutButton toggleLoggedIn={toggleLoggedIn} />
  else
    return <LoginButton toggleLoggedIn={toggleLoggedIn} />
}

export default App;

O código inclui comentários explicando como cada parte foi implementada.

Em seguida, tente executar o aplicativo com o seguinte comando:

npm start

Ao acessar a URL do aplicativo (isto é, http://localhost:3000), você verá um texto e um botão na tela:

Página do navegador exibindo “Você saiu da sua conta” com um botão “Entrar”.

Clique no botão Log In para alterar o estado e disparar uma nova renderização. Você verá que o texto e o botão mudam para os correspondentes a um usuário conectado:

Página do navegador em localhost:3000 exibindo “Você está conectado” e um botão “Sair”

E pronto! É muito fácil implementar a renderização condicional em React. A seguir, você verá como fazer isso em um aplicativo Next.js.

Como implementar a renderização e o roteamento condicionais em Next.js

Next.js é um framework opinativo, de código aberto e baseado em React, voltado para produção e que ajuda você a criar aplicações web de alto desempenho. Lançado pela Vercel em 2016, tornou-se um dos principais frameworks baseados em React no setor de desenvolvimento web.

O Next.js oferece suporte nativo à renderização no servidor e à renderização estática, além de soluções fáceis de usar para problemas comuns de desenvolvimento, como busca de dados, roteamento e ambientes de execução no servidor.

Como implementar a renderização condicional em Next.js

Como a sintaxe JSX é consistente no Next.js e no React, você pode aplicar técnicas de renderização condicional no Next.js da mesma forma que faria no React.

Para começar a usar Next.js, crie um novo aplicativo Next.js executando o seguinte comando:

npx create-next-app conditionals-next

Siga as instruções na tela para criar seu aplicativo. Você pode escolher as opções padrão (exceto TypeScript: selecione No). Depois de criar o projeto, cole o código a seguir no arquivo pages/index.js:

import { useState } from "react";

// Define two components
const LoginButton = (props) => {
  return <>
    <div>You are logged out</div>
    <div><button onClick={props.toggleLoggedIn}>Log In</button></div>
  </>
}

const LogoutButton = (props) => {
  return <>
    <div>You are now logged in</div>
    <div><button onClick={props.toggleLoggedIn}>Log Out</button></div>
  </>
}

export default function Home() {
  // Define a state that the condition will be based upon
  const [loggedIn, setLoggedIn] = useState(false);

  // Define a function that can change the condition value
  const toggleLoggedIn = () => {
    setLoggedIn((currState) => {
        return !currState;
    })
  }

  // Use the ternary conditional operator to render one out of two components based on login state
  return loggedIn 
  ? <LogoutButton toggleLoggedIn={toggleLoggedIn} /> 
  : <LoginButton toggleLoggedIn={toggleLoggedIn} />
}

O código inclui comentários explicando cada etapa. Uma diferença importante em relação ao exemplo com React é o uso do operador condicional ternário do JavaScript para escolher qual dos dois componentes renderizar. Você pode executar o aplicativo com o seguinte comando:

npm run dev

Quando o aplicativo iniciar, você verá algo parecido com isto em http://localhost:3000:

Página do navegador em localhost:3000 exibindo “Você está desconectado” com um botão “Fazer login”

Mais uma vez, você pode clicar no botão Log In para alterar o estado:

Página do navegador exibindo “Você está conectado” com um botão “Sair”

Como implementar o roteamento condicional em Next.js

Também é fácil implementar o roteamento condicional no Next.js 10 ou posterior. Para começar, crie um novo arquivo profile.js no diretório conditionals-next/pages e cole nele o trecho de código a seguir:

// This is the profile page
const Profile = () => {
  return <div>This is your profile</div>
}

// This function is called on the server side before the page is rendered
// Redirecting from this method means that the user will not see the page even for a flash of a second (which often happens in client-side redirection)
export async function getServerSideProps(context) {
    const allowAccess = false; // This is usually deduced from the authentication state of the user

    if (!allowAccess) {

        console.log("Redirecting to home...")

        return {
            redirect: {
                permanent: false,
                destination: "/"
            }
        }
    } else
        return { props: {} }
}

export default Profile

Depois, execute o aplicativo novamente e acesse http://localhost:3000/profile. Você será redirecionado imediatamente para a página inicial (isto é, a rota /). Consulte o terminal para ver o registro do redirecionamento:

# ... other output here
wait  - compiling...
event - compiled client and server successfully in 109 ms (199 modules)
wait  - compiling /profile (client and server)...
event - compiled client and server successfully in 114 ms (202 modules)
Redirecting to home...

Se você alterar o valor de allowAccess para true, poderá ver a página de perfil:

Janela do navegador em localhost:3000/profile exibindo o título “Este é o seu perfil” em uma página preta

Como implementar a renderização e o roteamento condicionais em Remix

Remix é outro framework baseado em React que vem ganhando espaço na criação de aplicações web. Ele prioriza os padrões da web e ajuda você a oferecer experiências melhores aos usuários. Remix se tornou de código aberto em 2021 e é um forte concorrente do Next.js.

Remix é um framework totalmente renderizado no servidor e oferece recursos como limites de erro integrados e gerenciamento de transições.

Como implementar a renderização condicional em Remix

Como Remix é baseado em React, você pode implementar a renderização condicional nele de forma semelhante ao que fez em React e Next.js.

Para começar, crie um novo projeto Remix executando o seguinte comando:

npx create-remix@latest

Siga as instruções para criar seu projeto. Escolha JavaScript, não TypeScript. Depois de criar o projeto, cole o trecho de código a seguir em app/routes/index.jsx:

import { useState } from "react";

// Define two components
const LoginButton = (props) => {
  return <>
    <div>You are logged out</div>
    <div><button onClick={props.toggleLoggedIn}>Log In</button></div>
  </>
}

const LogoutButton = (props) => {
  return <>
    <div>You are now logged in</div>
    <div><button onClick={props.toggleLoggedIn}>Log Out</button></div>
  </>
}

export default function Index() {
  // Define a state that the condition will be based upon
  const [loggedIn, setLoggedIn] = useState(false);

  // Define a function that can change the condition value
  const toggleLoggedIn = () => {
    setLoggedIn((currState) => {
        return !currState;
    })
  }

  // Use a switch statement to render one of two components based on login state
  switch(loggedIn) {
    case true: return <LogoutButton toggleLoggedIn={toggleLoggedIn} />
    case false: return <LoginButton toggleLoggedIn={toggleLoggedIn} />
    default: return null
  }
}

O trecho inclui comentários explicando cada etapa. Em vez de usar uma instrução if...else ou um operador condicional ternário, este exemplo usa uma instrução switch para decidir qual componente renderizar.

Assim como nos exemplos anteriores, veja como será a página inicial em http://localhost:3000:

Página do navegador em localhost:3000 exibindo “Você está desconectado” com um botão “Entrar”

Como nos exemplos anteriores, você pode clicar no botão Log In para alterar o estado:

Página do navegador exibindo “Você está conectado” com um botão “Sair”

Como implementar o roteamento condicional em Remix

Assim como você implementou o roteamento condicional no servidor em Next.js, também pode implementá-lo em Remix. Crie um novo arquivo, profile.jsx, no diretório conditionals-remix/app/routes e cole nele o código a seguir:

import { redirect } from '@remix-run/node'

const Profile = () => {
    return <div>This is your profile</div>
}

export const loader = () => {
    const allowAccess = false; // This is usually deduced from authentication state of the user

    if (!allowAccess) {
        console.log("Redirecting to home...")

        return redirect('/')
    }

    return null
}

export default Profile

Aqui, usamos uma função loader no lugar da função getServerSideProps, pois Remix oferece suporte a loaders para carregar dados nos componentes enquanto eles são renderizados no servidor (algo semelhante ao que getServerSideProps faz no Next.js). Além disso, retornamos a função utilitária redirect (semelhante à função redirect do Next.js) para iniciar um redirecionamento quando allowAccess estiver definido como false.

Acesse http://localhost:3000/profile e, mais uma vez, você será redirecionado imediatamente para a página inicial (isto é, a rota /). Consulte o terminal para ver o registro do redirecionamento:

# ... other output here
💿 Rebuilding...
💿 Rebuilt in 100ms
GET / 200 - - 17.179 ms
Redirecting to home...        #=== here it is
GET /profile 302 - - 7.107 ms
GET / 200 - - 6.564 ms

Se você alterar o valor de allowAccess para true, poderá ver a página de perfil:

Janela do navegador exibindo uma página de perfil com o título “Este é o seu perfil” em localhost:3000/profile.

Outros aspectos da renderização condicional

Ao trabalhar com renderização condicional, você pode se perguntar como ela afeta o DOM virtual. Os diferentes métodos de renderização condicional têm o mesmo desempenho? Criar um novo componente ou um componente de ordem superior (HOC) para abstrair os detalhes da renderização condicional afeta o DOM da sua aplicação (e seu desempenho)? Nesta seção, você vai encontrar as respostas.

Renderização condicional e JSX

A forma como você implementa a renderização condicional não afeta o DOM nem o desempenho da sua aplicação. Veja o exemplo a seguir:

if (loggedIn)
  return <button>Log Out</button>
else
  return <button>Log In</button>

Você também pode escrever assim, usando o operador condicional ternário:

return <button>{loggedIn ? "Log Out" : "Log In"}</button>

Em ambos os casos, o componente pai retornará um dos dois componentes (isto é, LoginButton e LogoutButton) e fará exatamente a mesma alteração no DOM. Talvez você argumente que cada opção retorna uma instância diferente da tag de botão, mas isso não é verdade. Elementos JSX, como botões e outras tags, não são instâncias. Eles são apenas uma descrição ou estrutura básica do HTML final.

Desde que você retorne os mesmos elementos com a mesma estrutura, o impacto no DOM será igual. Isso significa que você pode abstrair livremente a renderização em componentes, desde que a estrutura JSX seja a mesma.

Isso também abre espaço para situações interessantes, como compartilhar o mesmo estado entre dois componentes com estrutura idêntica, embora apenas um deles seja renderizado condicionalmente no mesmo lugar do DOM. Saiba mais no site do React, que mostra o grande impacto que um simples operador ternário em JSX pode ter no funcionamento do seu aplicativo.

Componentes aninhados e renderização condicional

Aninhar a definição de componentes dentro dos próprios componentes é considerado um antipadrão. Um dos principais motivos é que um componente aninhado é recriado sempre que o componente pai é renderizado novamente, independentemente de sua posição na árvore DOM. Esse comportamento é diferente do que você viu antes porque a definição do componente aninhado no runtime é recriada quando o componente pai é renderizado novamente. Isso é um pouco semelhante à criação de uma nova instância da definição do componente aninhado e, por isso, causa esse problema.

Conclusão e recursos adicionais

Embora a renderização condicional pareça (e seja) bastante simples à primeira vista, ela é uma técnica muito poderosa para melhorar o desempenho e a experiência do usuário em apps React. Neste artigo, você conheceu seus benefícios e viu como ela difere do roteamento condicional, além de aprender a implementá-la no React, no Next.js e no Remix.

Para saber mais sobre renderização condicional e como o React gerencia o estado entre renderizações, confira a nova documentação do React.

Ao desenvolver apps React, você frequentemente precisa selecionar e instalar pacotes npm para adicionar funcionalidades, como roteamento e gerenciamento de estado. O Snyk Advisor ajuda você a encontrar o pacote npm ideal para seu projeto sem abrir mão de padrões rigorosos de segurança para o app. Confira também nossa lista de 10 boas práticas de segurança para adotar ao trabalhar com React.

O Snyk também pode ser usado como uma extensão de IDE para encontrar código inseguro em bases de código React e ajudar você a corrigir vulnerabilidades de segurança em dependências de código aberto.

Comece a resolver desafios de capture the flag

Aprenda a resolver desafios de capture the flag assistindo sob demanda ao nosso workshop virtual introdutório.

Leia mais

feature insights context
Blog

Os ataques autônomos já chegaram. A defesa precisa acompanhar o ritmo.

Os atacantes autônomos estão reduzindo o tempo disponível para a defesa. Saiba como a descoberta, a correção, a validação e a prevenção contínuas ajudam as equipes de segurança a acompanhar esse ritmo.

Blog

Por que agentes de programação com IA continuam criando falhas de controle de acesso

Agentes de programação com IA podem gerar uma lógica de autorização que compila e passa pela revisão, mas permite que um tenant acesse os dados de outro. Saiba por que é difícil detectar falhas de controle de acesso e como evitá-las.

Blog

Evo ADS Govern Agent Behavior já está disponível: controle o uso de MCP

Evo ADS Govern Agent Behavior já está disponível, começando por MCP Governance. Descubra, aprove, monitore, registre e bloqueie o uso de servidores MCP nos principais agentes de programação com IA.