Skip to main content

Renderização Condicional

Trabalhar com renderização condicional no React é bastante simples. Normalmente que trabalha com frameworks e biblitoecas Front-End pode imaginar a utilização de if/else para fazer a renderização de algum elementom as existem formas mais simples.

Ao invés de:

if (isLoggedIn) {
return <UserGreeting />;
} else {
return <GuestGreeting />;
}

Você pode utilizar o operador ternário:

return isLoggedIn ? <UserGreeting /> : <GuestGreeting />;

Dessa forma o código fica muito mais limpo e fácil de ler.

Também é possível utilizar o operador && para fazer a renderização condicional:

isLoggedIn && <UserGreeting />;

Algo bem comum no dia-a-dia é utilização de ternários e verificação se uma condição é verdadeira e caso seja renderizar um elemento.

Imagem uma listagem de usuários e você quer renderizar um botão de excluir apenas para usuários que possuem o nível de acesso admin.

const users = [
{ name: "John", role: "admin" },
{ name: "Jane", role: "user" },
{ name: "Mary", role: "user" },
];

const UserList = () => {
return (
<ul>
{users.map((user) => (
<li key={user.name}>
{user.name} {user.role === "admin" && <button>Excluir</button>}
</li>
))}
</ul>
);
};

Elemento Variável

Você pode utilizar variáveis para armazenar elementos. Isso pode ser útil para renderizar um elemento ou outro dependendo de uma condição.

const UserGreeting = () => <h1>Bem-vindo de volta!</h1>;

const GuestGreeting = () => <h1>Por favor, faça login.</h1>;

const Greeting = ({ isLoggedIn }) => {
if (isLoggedIn) {
return <UserGreeting />;
}
return <GuestGreeting />;
};

const App = () => {
const isLoggedIn = true; //image que exista aqui um retorno de um serviço que verifica as credenciais do usuário e o token de acesso
return <Greeting isLoggedIn={isLoggedIn} />;
};

Boas práticas

Utilização de operadores ternários

Algo muito comum é a utilização de operadores ternários para fazer a renderização condicional do código, porém devemos tomar cuidado pra não deixá-lo muito complexo, dificultando a leitra, manutenção, evolução e testes.

Sem contar que a chance de causar um 🐛 aumenta consideravelmente.

// Algo para EVITAR a ser feito

// algumas importações que foram utilizadas abaixo

function Page({ type = "advanced" }) {
return (
<div>
{type === "advanced" ? (
<div>
<h1>Level Advanced</h1>
<p>Texto</p>
<img src="imagem.png" alt="Imagem" />
<div>
<Wallet level={level} />
<Dashboard />
<Button action={handle} />
</div>
</div>
) : type === "basic" ? (
<div>
<h1>Level Basic</h1>
<p>Texto 1</p>
<p>Texto 2</p>
<img src="imagem.png" alt="Imagem" />
<div>
<Wallet level={level} />
<Button action={handle} />
</div>
</div>
) : (
<div>
<p>Texto</p>
<div>
<CreateAccount />
<Button action={handle} />
</div>
</div>
)}
</div>
);
}

O código acima funciona? Sim, perfeitamente.

Mas com a evolução, adição de novos componentes, lógicas e etc, essa abordagem pode ficar bastante confusa, dificultando inclusive o entendimento.

info

O código acima apresenta alguns problemas:

  • Repetição de código, que leva a um aumento desnecessário da complexidade;
  • Dificuldade de compreensão, tornando o código menos acessível para outros desenvolvedores;
  • Desafios para aplicação de testes unitários, pois é necessário testar todas as condições da página;
  • Falta de componentização, o que poderia simplificar a estrutura do código;
  • Complexidade devido ao uso excessivo de condicionais (ternário, if/else, switch-case, etc.);
  • O código se torna uma "tripa", ou seja, muito extenso e enrolado 🏄.

Isso é algo bastante comum no cotidiano de desenvolvimento. Com facilidade, mais código é adicionado, complicando o entendimento da página.

Uma forma de melhorar o código é a criação de componentes específicos para cada type e criar um mapa de componentes para realizar a renderização baseado em uma propriedade.

// Algo MELHOR a ser feito

import { AdvancedAccount } from "./AdvancedAccount";
import { BasicAccount } from "./BasicAccount";
import { CreateAccount } from "./CreateAccount";

function getPageComponent(type) {
// mapa de componentes
const components = {
advanced: AdvancedAccount,
basic: BasicAccount,
default: CreateAccount,
};

// caso o tipo não exista no mapa, retorna o componente padrão
return components[type] || components["default"];
}

function Page({ type = "advanced" }) {
const Component = getPageComponent(type);

return (
<div>
<Component />
</div>
);
}

Por que essa abordagem é melhor? Consome mais memória? É mais lenta?

Não, a abordagem é melhor porque deixa o código mais limpo, fácil de ler e entender, além de facilitar a manutenção e evolução do código.

Com a evolução da lógica, podemos simplesmente adicionar novos componentes ao mapa, mantendo o mesmo formato. Isso facilita a adição de testes unitários, pois podemos testar a função getPageComponent isoladamente, passando simplesmente o atributo type, sem ter que renderizar a página várias vezes para cobrir cada caso de uso.

As duas abordagens funcionam? Como já mencionado, sim. Mas é sempre bom pensar em boas práticas para manter o código organizado e fácil de evoluir. É muito importante lembrar que não seremos os únicos a trabalhar em um sistema e, mesmo que fôssemos, com certeza amanhã não vamos lembrar o que estávamos pensando naquele dia do desenvolvimento, tornando necessário revisar todo o código.

warning

É essencial ressaltar que esta prática não é recomendada para todas as situações. Frequentemente, um excesso de condicionais indica problemas na arquitetura do código.

Buscar sempre a simplicidade e a clareza no código é o ideal. O uso de operadores ternários é aceitável, mas é prudente limitá-lo a casos mais específicos e evitar exageros.

Quer mais boas práticas? Clique aqui.