Renderização condicional
Seus componentes frequentemente precisarão exibir coisas diferentes dependendo de diferentes condições. No React, você pode renderizar condicionalmente JSX usando sintaxe do JavaScript, como declarações if
, e operadores ? :
e &&
.
Você aprenderá
- Como retornar diferentes JSX dependendendo de uma condição
- Como incluir ou excluir condicionalmente um trecho de JSX
- Atalhos de sintaxe condicional comuns que você encontrará em bases de código do React
Retorno condicional de JSX
Digamos que você tenha um componente PackingList
renderizando vários Item
s, que podem ser marcados como empacotados ou não:
function Item({ name, isPacked }) { return <li className="item">{name}</li>; } export default function PackingList() { return ( <section> <h1>Packing List de Sally Ride</h1> <ul> <Item isPacked={true} name="Traje espacial" /> <Item isPacked={true} name="Capacete com folha dourada" /> <Item isPacked={false} name="Foto de Tam" /> </ul> </section> ); }
Observe que alguns dos componentes Item
possuem a propriedade isPacked
definida como true
ao invés de false
. Você deseja adicionar uma marca de seleção (✔) aos itens empacotados se isPacked={true}
.
Você pode escrever isso como uma declaração if
/else
da seguinte maneira:
if (isPacked) {
return <li className="item">{name} ✔</li>;
}
return <li className="item">{name}</li>;
Se a propriedade isPacked
for true
, este código retorna uma árvore JSX diferente. Com essa alteração, alguns dos itens recebem uma marca de seleção no final:
function Item({ name, isPacked }) { if (isPacked) { return <li className="item">{name} ✔</li>; } return <li className="item">{name}</li>; } export default function PackingList() { return ( <section> <h1>Packing List de Sally Ride</h1> <ul> <Item isPacked={true} name="Traje espacial" /> <Item isPacked={true} name="Capacete com folha dourada" /> <Item isPacked={false} name="Foto de Tam" /> </ul> </section> ); }
Experimente editar o que é retornado em cada caso e veja como o resultado muda!
Observe como você está criando lógica de ramificação com as declarações if
e return
do JavaScript. No React, o fluxo de controle (como condições) é tratado pelo JavaScript.
Retornando condicionalmente nada com null
Em algumas situações, você não desejará renderizar nada. Por exemplo, digamos que você não queira mostrar itens embalados de jeito nenhum. Um componente deve retornar algo. Nesse caso, você pode retornar null
:
if (isPacked) {
return null;
}
return <li className="item">{name}</li>;
Se isPacked
equivaler à true
, o componente não retornará nada, null
. Caso contrário, retornará o JSX para ser renderizado.
function Item({ name, isPacked }) { if (isPacked) { return null; } return <li className="item">{name}</li>; } export default function PackingList() { return ( <section> <h1>Packing List de Sally Ride</h1> <ul> <Item isPacked={true} name="Traje espacial" /> <Item isPacked={true} name="Capacete com folha dourada" /> <Item isPacked={false} name="Foto de Tam" /> </ul> </section> ); }
Na prática, retornar null
de um componente não é comum porque pode surpreender um desenvolvedor que está tentando renderizá-lo. Com mais frequência, você condicionalmente incluiria ou excluíria o componente no JSX do componente pai. Veja como fazer isso!
Incluindo JSX condicionalmente
No exemplo anterior, você controlou qual (se houver) árvore JSX seria retornada pelo componente. Você pode ter percebido alguma duplicação na saída de renderização:
<li className="item">{name} ✔</li>
é muito semelhante a
<li className="item">{name}</li>
Ambas as ramificações condicionais retornam <li className="item">...</li>
:
if (isPacked) {
return <li className="item">{name} ✔</li>;
}
return <li className="item">{name}</li>;
Embora essa duplicação não seja prejudicial, ela pode tornar seu código mais difícil de manter. E se você quiser alterar a className
? Você teria que fazer isso em dois lugares do seu código! Em tal situação, você poderia incluir condicionalmente um pouco de JSX para tornar seu código mais DRY.
Operador condicional ternário (? :
)
O JavaScript possui uma sintaxe compacta para escrever uma expressão condicional — o operador condicional ou “operador ternário”.
Ao invés disso:
if (isPacked) {
return <li className="item">{name} ✔</li>;
}
return <li className="item">{name}</li>;
Você pode escrever isso:
return (
<li className="item">
{isPacked ? name + ' ✔' : name}
</li>
);
Você pode interpretá-lo como “se isPacked
for true
, então (?
) renderize name + ' ✔'
, caso contrário (:
) renderize name
”.
Deep Dive
Se você vem de um histórico de programação orientada a objetos, você pode supor que os dois exemplos acima são sutilmente diferentes porque um deles pode criar duas “instâncias” diferentes de <li>
. No entanto, os elementos JSX não são “instâncias” porque eles não possuem nenhum estado interno e não são nós reais do DOM. Eles são leves descrições, como plantas baixas. Portanto, esses dois exemplos, na verdade, são completamente equivalentes. Preservando e redefinindo o estado explora em detalhes como isso funciona.
Agora, vamos supor que você queira envolver o texto do item concluído em outra tag HTML, como <del>
, para eliminá-lo. Você pode adicionar ainda mais quebras de linha e parênteses para facilitar a aninhamento de mais JSX em cada um dos casos:
function Item({ name, isPacked }) { return ( <li className="item"> {isPacked ? ( <del> {name + ' ✔'} </del> ) : ( name )} </li> ); } export default function PackingList() { return ( <section> <h1>Packing List de Sally Ride</h1> <ul> <Item isPacked={true} name="Traje espacial" /> <Item isPacked={true} name="Capacete com folha dourada" /> <Item isPacked={false} name="Foto de Tam" /> </ul> </section> ); }
Este estilo funciona bem para condições simples, mas use-o com moderação. Se seus componentes ficarem bagunçados com marcação condicional aninhada demais, considere extrair componentes filhos para limpar as coisas. No React, a marcação faz parte do seu código, então você pode usar ferramentas como variáveis e funções para organizar expressões complexas.
Operador lógico AND (&&
)
Outro atalho comum que você encontrará é o operador JavaScript AND lógico (&&
). Dentro de componentes React, ele geralmente é usado quando você deseja renderizar algum JSX quando a condição for verdadeira, ou não renderizar nada caso contrário. Com &&
, você pode renderizar condicionalmente o marcador de verificação apenas se isPacked
for true
:
return (
<li className="item">
{name} {isPacked && '✔'}
</li>
);
Você pode interpretar isso como “se isPacked
, então (&&
) renderize o marcador de verificação, caso contrário, não renderize nada”.
Veja como funciona na prática:
function Item({ name, isPacked }) { return ( <li className="item"> {name} {isPacked && '✔'} </li> ); } export default function PackingList() { return ( <section> <h1>Packing List de Sally Ride</h1> <ul> <Item isPacked={true} name="Traje espacial" /> <Item isPacked={true} name="Capacete com folha dourada" /> <Item isPacked={false} name="Foto de Tam" /> </ul> </section> ); }
A Express JavaScript && retorna o valor do seu lado direito (no nosso caso, o marcador de verificação) se o lado esquerdo (a nossa condição) for true
. Mas se a condição for false
, a expressão inteira se torna false
. O React considera false
como um “vazio” na árvore JSX, assim como null
ou undefined
, e não renderiza nada em seu lugar.
Atribuindo condicionalmente JSX à uma variável
Quando os atalhos atrapalham a escrita de código simples, tente usar uma declaração if
e uma variável. Você pode reatribuir variáveis definidas com let
, portanto, comece fornecendo o conteúdo padrão que você deseja exibir, o nome:
let itemContent = name;
Use uma declaração if
para reatribuir uma expressão JSX a itemContent
se isPacked
for true
:
if (isPacked) {
itemContent = name + " ✔";
}
As chaves abrem a “janela para o JavaScript”. Incorpore a variável com chaves na árvore JSX retornada, aninhando a expressão previamente calculada dentro do JSX:
<li className="item">
{itemContent}
</li>
Este estilo é o mais verbose, mas também o mais flexível. Veja como funciona na prática:
function Item({ name, isPacked }) { let itemContent = name; if (isPacked) { itemContent = name + " ✔"; } return ( <li className="item"> {itemContent} </li> ); } export default function PackingList() { return ( <section> <h1>Packing List de Sally Ride</h1> <ul> <Item isPacked={true} name="Traje espacial" /> <Item isPacked={true} name="Capacete com folha dourada" /> <Item isPacked={false} name="Foto de Tam" /> </ul> </section> ); }
Como antes, isso funciona não apenas para texto, mas também para JSX arbitrário:
function Item({ name, isPacked }) { let itemContent = name; if (isPacked) { itemContent = ( <del> {name + " ✔"} </del> ); } return ( <li className="item"> {itemContent} </li> ); } export default function PackingList() { return ( <section> <h1>Packing List de Sally Ride</h1> <ul> <Item isPacked={true} name="Traje espacial" /> <Item isPacked={true} name="Capacete com folha dourada" /> <Item isPacked={false} name="Foto de Tam" /> </ul> </section> ); }
Se você não está familiarizado com JavaScript, essa variedade de estilos pode parecer avassaladora no início. No entanto, aprender esses estilos ajudará você a ler e escrever qualquer código JavaScript, e não apenas componentes React! Escolha aquele que você preferir para começar e consulte esta referência novamente se você esquecer como os outros funcionam.
Recap
- No React, você controla a lógica de ramificação com JavaScript.
- Você pode retornar uma expressão JSX condicionalmente com uma declaração
if
. - Você pode salvar condicionalmente algum JSX em uma variável e depois incluí-lo dentro de outro JSX usando chaves.
- No JSX,
{cond ? <A /> : <B />}
significa “second
, renderize<A />
, caso contrário,<B />
”. - No JSX,
{cond && <A />}
significa “second
, renderize<A />
, caso contrário, nada”. - Os atalhos são comuns, mas você não precisa usá-los se preferir usar um
if
simples.
Challenge 1 of 3: Mostre um ícone para itens incompletos com ? :
Use o operador condicional (cond ? a : b
) para renderizar um ❌ se isPacked
não for true
.
function Item({ name, isPacked }) { return ( <li className="item"> {name} {isPacked && '✔'} </li> ); } export default function PackingList() { return ( <section> <h1>Packing List de Sally Ride</h1> <ul> <Item isPacked={true} name="Traje espacial" /> <Item isPacked={true} name="Capacete com folha dourada" /> <Item isPacked={false} name="Foto de Tam" /> </ul> </section> ); }