Fundamentos de React: Componentes, Dados e APIs

Guia operacional para props, listas, estado, agrupamentos e consumo de APIs

Por Fábio Linhares • Instituto Infnet

Apresentação das questões

As questões desta página treinam uma competência central de front-end: transformar requisito em interface funcional com explicação técnica clara. O desafio não é decorar sintaxe; é modelar dados, compor componente e validar comportamento na tela.

O percurso mistura quatro frentes complementares: componentização com props, transformação de listas (incluindo agrupamento e ordenação), interação com estado local e integração com APIs externas reais.

Quem fecha os 16 exercícios com entendimento real demonstra domínio inicial consistente de React aplicado a problemas práticos, incluindo fluxo de dados, renderização previsível e leitura correta de payloads.

  • Componentes como contratos de entrada e saída.
  • Listas com map, agrupamento com reduce e ordenação com critério.
  • Estado local com useState para inputs, seleções e resultados.
  • Fetch com tratamento de resposta e exibição legível.
  • Separação entre lógica de dados e composição visual.
// App.jsx (modelo de execução)
import Ex01 from "./Ex01";
// import Ex02 from "./Ex02";
// ...

export default function App() {
  return <Ex01 />;
}
EXERCÍCIO 01
Saudação parametrizada por props
Criar componente reutilizável com nome recebido por props e renderizar 3 exemplos.
function Saudacao({ nome }) {
  return (
    <div className="card">
      <h2>Olá, {nome}!</h2>
      <p>Seja bem-vindo(a) ao React.</p>
    </div>
  );
}

export default function Ex01() {
  return (
    <div className="page">
      <Saudacao nome="Ana" />
      <Saudacao nome="Bruno" />
      <Saudacao nome="Carla" />
    </div>
  );
}
O que a questão pede
Criar um componente reutilizável que receba o nome por props e renderizar três instâncias com valores diferentes.
Conceito cobrado
Uso de props como entrada do componente e reaproveitamento da mesma estrutura sem duplicar JSX.
Estrutura dos dados

A entrada do componente é simples: { nome }. A saída é sempre o mesmo card, mudando apenas o valor recebido.

Como pensar
Primeiro defina o contrato mínimo do componente, depois reutilize-o com valores diferentes para provar que ele não depende de texto fixo.
Como validar
A tela deve mostrar três saudações com nomes diferentes usando o mesmo componente.
Erro comum: escrever três blocos quase iguais em vez de criar um único componente parametrizado.
EXERCÍCIO 02
Saudação com data e ano bissexto
Adicionar props de data e destacar ano bissexto com regra correta.
function isLeapYear(year) {
  return (year % 4 === 0 && year % 100 !== 0) || (year % 400 === 0);
}

function SaudacaoNascimento({ nome, dia, mes, ano }) {
  const bissexto = isLeapYear(ano);
  return (
    <div className="card">
      <h2>Olá, {nome}!</h2>
      <p>Nascimento: {String(dia).padStart(2, "0")}/{String(mes).padStart(2, "0")}/{ano}</p>
      <p>Ano: <strong style={{ color: bissexto ? "green" : "#444" }}>{ano}</strong>{bissexto && " (bissexto)"}</p>
    </div>
  );
}

export default function Ex02() {
  return (
    <div className="page">
      <SaudacaoNascimento nome="Ana" dia={4} mes={3} ano={2000} />
      <SaudacaoNascimento nome="Bruno" dia={12} mes={7} ano={1999} />
      <SaudacaoNascimento nome="Carla" dia={29} mes={2} ano={2024} />
    </div>
  );
}
O que a questão pede
Adicionar data de nascimento por props e aplicar a regra correta para destacar anos bissextos.
Conceito cobrado
Combinar props com lógica derivada dentro do componente sem misturar regra de calendário com apresentação fixa.
Estrutura dos dados

As entradas são { nome, dia, mes, ano }. O valor bissexto não vem de fora; ele é derivado de ano.

Como pensar
Separe o problema em duas partes: formatar os dados recebidos e calcular, a partir do ano, a condição que muda a interface.
Como validar
Ano 2000 deve aparecer com destaque e marcação de bissexto; 1999 não deve receber a mesma indicação.
Erro comum: tratar qualquer múltiplo de 4 como bissexto e ignorar a exceção dos séculos.
EXERCÍCIO 03
Avaliação com estrelas e título de filme
Renderizar fila de estrelas por props e mostrar 5 filmes.
function AvaliacaoFilme({ titulo, totalEstrelas, avaliacao }) {
  return (
    <div className="card">
      {Array.from({ length: totalEstrelas }, (_, i) => (
        <span key={i} style={{ color: i < avaliacao ? "red" : "#bbb", fontSize: 24 }}>★</span>
      ))}
      <strong style={{ marginLeft: 12 }}>{titulo}</strong>
    </div>
  );
}

const filmes = [
  { titulo: "Matrix", totalEstrelas: 5, avaliacao: 5 },
  { titulo: "Interestelar", totalEstrelas: 5, avaliacao: 4 },
  { titulo: "Arrival", totalEstrelas: 5, avaliacao: 4 },
  { titulo: "Blade Runner 2049", totalEstrelas: 5, avaliacao: 5 },
  { titulo: "Duna", totalEstrelas: 5, avaliacao: 4 }
];

export default function Ex03() {
  return (
    <div className="page">
      {filmes.map((filme) => (
        <AvaliacaoFilme key={filme.titulo} {...filme} />
      ))}
    </div>
  );
}
O que a questão pede
Mostrar cinco filmes e representar a avaliação de cada um com estrelas preenchidas e vazias.
Conceito cobrado
Renderização derivada a partir de props numéricas e geração controlada de repetições com Array.from.
Estrutura dos dados

Cada filme segue { titulo, totalEstrelas, avaliacao }. O número de estrelas ativas é calculado comparando o índice com avaliacao.

Como pensar
Em vez de desenhar estrela por estrela manualmente, gere a quantidade total e marque visualmente apenas as posições abaixo da nota.
Como validar
Cada linha deve exibir a quantidade correta de estrelas ativas e inativas, sem ultrapassar o total definido.
Erro comum: confundir quantidade total com nota e renderizar mais ou menos estrelas do que o componente deveria suportar.
EXERCÍCIO 04
Avaliação com cor parametrizável
Permitir cor de estrela por prop sem duplicar componente.
function AvaliacaoFilme({ titulo, totalEstrelas, avaliacao, cor = "red" }) {
  return (
    <div className="card">
      {Array.from({ length: totalEstrelas }, (_, i) => (
        <span key={i} style={{ color: i < avaliacao ? cor : "#bbb", fontSize: 24 }}>★</span>
      ))}
      <strong style={{ marginLeft: 12 }}>{titulo}</strong>
    </div>
  );
}

export default function Ex04() {
  return (
    <div className="page">
      <AvaliacaoFilme titulo="Matrix" totalEstrelas={5} avaliacao={5} cor="crimson" />
      <AvaliacaoFilme titulo="Interestelar" totalEstrelas={5} avaliacao={4} cor="goldenrod" />
      <AvaliacaoFilme titulo="Arrival" totalEstrelas={5} avaliacao={4} cor="deepskyblue" />
    </div>
  );
}
O que a questão pede
Permitir que a cor das estrelas seja definida por prop, mantendo o mesmo componente para filmes diferentes.
Conceito cobrado
Separação entre lógica de componente e parâmetro visual de apresentação.
Estrutura dos dados

O contrato passa a ser { titulo, totalEstrelas, avaliacao, cor }. A prop cor altera apenas o estilo das estrelas ativas.

Como pensar
Quando uma variação atinge apenas a aparência, transforme-a em prop em vez de duplicar componente ou criar versões fixas.
Como validar
Os filmes devem manter a mesma estrutura de estrelas, mudando apenas a cor das estrelas preenchidas conforme a prop enviada.
Erro comum: criar um componente por cor e perder o ganho principal de reutilização.
EXERCÍCIO 05
Lista de funcionários com Faker
Gerar 10 funcionários com id, nome, cargo e departamento.
import { faker } from "@faker-js/faker";

const funcionarios = Array.from({ length: 10 }, () => ({
  id: faker.string.uuid(),
  nome: faker.person.fullName(),
  cargo: faker.person.jobTitle(),
  departamento: faker.commerce.department()
}));

export default function Ex05() {
  return (
    <ul>
      {funcionarios.map((f) => (
        <li key={f.id}>
          {f.nome} - {f.cargo} ({f.departamento})
        </li>
      ))}
    </ul>
  );
}
O que a questão pede
Gerar 10 objetos de funcionário e renderizar uma lista simples com nome, cargo e departamento.
Conceito cobrado
Mapeamento de array em JSX e uso de key estável para cada item.
Estrutura dos dados

Cada item segue { id, nome, cargo, departamento }. O campo id é usado na key e não deve ser trocado por índice.

Como pensar
Primeiro monte o array com Faker, depois valide o formato de cada objeto e só então renderize com map.
Como validar
A tela precisa mostrar exatamente 10 linhas e cada linha deve seguir o padrão: nome - cargo (departamento).
Erro comum: usar key={index} e perder estabilidade de renderização quando a lista muda.
EXERCÍCIO 06
Funcionários agrupados por departamento
Gerar 30 itens e agrupar por departamento com saída organizada.
import { faker } from "@faker-js/faker";

const funcionarios = Array.from({ length: 30 }, () => ({
  id: faker.string.uuid(),
  nome: faker.person.fullName(),
  departamento: faker.commerce.department()
}));

const grupos = funcionarios.reduce((acc, f) => {
  if (!acc[f.departamento]) acc[f.departamento] = [];
  acc[f.departamento].push(f);
  return acc;
}, {});

export default function Ex06() {
  return (
    <div>
      {Object.entries(grupos).map(([dep, lista]) => (
        <section key={dep} className="card">
          <h3>{dep}</h3>
          <ul>{lista.map((f) => <li key={f.id}>{f.nome}</li>)}</ul>
        </section>
      ))}
    </div>
  );
}
O que a questão pede
Agrupar 30 funcionários por departamento e exibir cada grupo em bloco separado.
Conceito cobrado
reduce para construir objeto de agrupamento e Object.entries para renderizar.
Estrutura dos dados

O acumulador vira um objeto como { "TI": [...], "Vendas": [...] }. Cada chave é um departamento e cada valor é um array de funcionários.

Como pensar
Separar por etapa: gerar lista base, agrupar por chave e só depois mapear cada grupo para UI.
Como validar
A soma dos itens em todos os grupos deve continuar 30. Nenhum funcionário pode desaparecer no agrupamento.
Erro comum: confundir ordenar com agrupar. Ordenação só muda a ordem; agrupamento muda a estrutura.
EXERCÍCIO 07
Lista de produtos em formato e-commerce
Renderizar 50 produtos com nome, descrição, adjetivo e preço.
import { faker } from "@faker-js/faker";

const produtos = Array.from({ length: 50 }, () => ({
  id: faker.string.uuid(),
  nome: faker.commerce.productName(),
  descricao: faker.commerce.productDescription(),
  adjetivo: faker.commerce.productAdjective(),
  preco: faker.commerce.price({ min: 10, max: 900 })
}));

export default function Ex07() {
  return (
    <div className="grid">
      {produtos.map((p) => (
        <article key={p.id} className="card">
          <h3>{p.nome}</h3>
          <p>{p.descricao}</p>
          <strong>{p.adjetivo}</strong>
          <p>R$ {p.preco}</p>
        </article>
      ))}
    </div>
  );
}
O que a questão pede
Montar catálogo com 50 produtos e apresentar os campos principais em layout de cards.
Conceito cobrado
Renderização de lista longa com componente repetível e responsabilidade clara de cada campo.
Estrutura dos dados

Cada produto segue { id, nome, descricao, adjetivo, preco }. O preço do Faker vem como string e já pode ser exibido.

Como pensar
Defina o shape do produto, gere a coleção e renderize cada card mantendo hierarquia visual consistente.
Como validar
A lista precisa renderizar 50 cards sem falhas de chave, com todos os quatro campos visíveis.
Erro comum: esquecer que preco pode vir como string e tentar fazer conta sem converter.
EXERCÍCIO 08
Produtos agrupados por departamento
Agrupar lista de produtos por departamento sem perder legibilidade.
import { faker } from "@faker-js/faker";

const produtos = Array.from({ length: 50 }, () => ({
  id: faker.string.uuid(),
  nome: faker.commerce.productName(),
  preco: faker.commerce.price({ min: 10, max: 900 }),
  departamento: faker.commerce.department()
}));

const porDepartamento = produtos.reduce((acc, p) => {
  if (!acc[p.departamento]) acc[p.departamento] = [];
  acc[p.departamento].push(p);
  return acc;
}, {});

export default function Ex08() {
  return (
    <div>
      {Object.entries(porDepartamento).map(([dep, itens]) => (
        <section key={dep} className="card">
          <h3>{dep}</h3>
          {itens.map((p) => <p key={p.id}>{p.nome} - R$ {p.preco}</p>)}
        </section>
      ))}
    </div>
  );
}
O que a questão pede
Separar os produtos por departamento e manter leitura simples por bloco.
Conceito cobrado
Transformação de lista em estrutura agrupada e renderização em dois níveis: grupo e item.
Estrutura dos dados

Entrada: array de produtos. Saída: objeto indexado por departamento com arrays internos de itens.

Como pensar
Modele a transformação com reduce e trate o resultado como dado derivado da lista base.
Como validar
Todo departamento exibido deve ter ao menos um produto, e o total final de itens precisa bater com a lista original.
Erro comum: renderizar grupo sem garantir chave única por departamento.
EXERCÍCIO 09
Consulta de CEP com ViaCEP
Consultar CEP digitado e exibir endereço completo.
const [cep, setCep] = useState("");
const [endereco, setEndereco] = useState(null);
const [erro, setErro] = useState("");

async function buscarCep() {
  const limpo = cep.replace(/\D/g, "");
  if (limpo.length !== 8) {
    setEndereco(null);
    setErro("Informe um CEP com 8 dígitos.");
    return;
  }

  const res = await fetch(`https://viacep.com.br/ws/${limpo}/json/`);
  const data = await res.json();
  if (data.erro) {
    setEndereco(null);
    setErro("CEP não encontrado.");
    return;
  }

  setErro("");
  setEndereco(data);
}

<input value={cep} onChange={(e) => setCep(e.target.value)} placeholder="Digite o CEP" />
<button onClick={buscarCep}>Buscar</button>
{erro && <p>{erro}</p>}
{endereco && <p>{endereco.logradouro}, {endereco.bairro} - {endereco.localidade}/{endereco.uf}</p>}
O que a questão pede
Ler o CEP do input, consultar a API e mostrar endereço completo quando houver retorno válido.
Conceito cobrado
Fluxo de estado + evento + requisição assíncrona + renderização condicional.
Estrutura dos dados

O ViaCEP retorna campos como logradouro, bairro, localidade e uf; em erro, retorna erro: true.

Como pensar
Sequência: limpar CEP, validar tamanho, buscar JSON, tratar erro e só então atualizar a interface.
Como validar
Com CEP válido (ex.: 01001000), o endereço aparece; com CEP inválido, a mensagem de erro aparece sem quebrar a tela.
Erro comum: disparar fetch com CEP incompleto e interpretar resposta vazia como sucesso.
EXERCÍCIO 10
Ranking de nomes por década (IBGE)
Normalizar década e carregar ranking da API IBGE.
const [ano, setAno] = useState("");
const [ranking, setRanking] = useState([]);
const [erro, setErro] = useState("");

async function buscarRanking() {
  const anoNum = Number(ano);
  if (!Number.isFinite(anoNum)) {
    setErro("Informe um ano numérico.");
    setRanking([]);
    return;
  }

  const decada = Math.floor(anoNum / 10) * 10;
  const url = `https://servicodados.ibge.gov.br/api/v2/censos/nomes/ranking/?decada=${decada}`;
  const res = await fetch(url);
  const data = await res.json();
  const lista = data[0]?.res || [];

  setErro("");
  setRanking(lista.slice(0, 10));
}

<input value={ano} onChange={(e) => setAno(e.target.value)} placeholder="Ano" />
<button onClick={buscarRanking}>Consultar</button>
{erro && <p>{erro}</p>}
<ol>{ranking.map((item) => <li key={item.nome}>{item.nome} ({item.frequencia})</li>)}</ol>
O que a questão pede
Receber um ano, normalizar para década e listar ranking de nomes retornado pela API do IBGE.
Conceito cobrado
Normalização de entrada, fetch assíncrono e renderização de coleção retornada por API.
Estrutura dos dados

O retorno vem como array e os nomes ficam em data[0].res, cada item contendo nome e frequencia.

Como pensar
Valide o ano, converta para década, consulte a API e renderize apenas a lista útil para leitura.
Como validar
Ano 1993 deve consultar 1990; ano 2001 deve consultar 2000. A lista exibida deve mudar conforme a década.
Erro comum: consultar década inválida por não converter corretamente o valor do input.
EXERCÍCIO 11
Carregar UF em dropdown (IBGE)
Popular select de unidades da federação sob demanda.
const [ufs, setUfs] = useState([]);
const [carregando, setCarregando] = useState(false);

async function carregarUFs() {
  setCarregando(true);
  const res = await fetch("https://servicodados.ibge.gov.br/api/v1/localidades/estados?orderBy=nome");
  const data = await res.json();
  setUfs(data);
  setCarregando(false);
}

<button onClick={carregarUFs} disabled={carregando}>
  {carregando ? "Carregando..." : "Carregar UFs"}
</button>

<select>
  <option value="">Selecione</option>
  {ufs.map((uf) => (
    <option key={uf.id} value={uf.sigla}>
      {uf.sigla} - {uf.nome}
    </option>
  ))}
</select>
O que a questão pede
Buscar as UFs na API e preencher um dropdown para seleção pelo usuário.
Conceito cobrado
Carregamento sob demanda com estado de lista e renderização dinâmica de opções.
Estrutura dos dados

Cada UF retorna no formato { id, sigla, nome }. Use id como chave da opção.

Como pensar
Separe claramente estado de carregamento e estado de dados para a interface não ficar ambígua.
Como validar
Após clicar em carregar, o select deve sair de vazio para lista completa de UFs em ordem alfabética.
Erro comum: mapear no select antes de garantir que o array de UFs já foi carregado.
EXERCÍCIO 12
Carregar municípios ao selecionar UF
Encadear consulta de municípios a partir da UF selecionada.
const [uf, setUf] = useState("");
const [municipios, setMunicipios] = useState([]);

useEffect(() => {
  if (!uf) {
    setMunicipios([]);
    return;
  }

  fetch(`https://servicodados.ibge.gov.br/api/v1/localidades/estados/${uf}/municipios`)
    .then((r) => r.json())
    .then((lista) => setMunicipios(lista));
}, [uf]);

<select value={uf} onChange={(e) => setUf(e.target.value)}>
  <option value="">Selecione UF</option>
  {ufs.map((item) => <option key={item.id} value={item.sigla}>{item.sigla}</option>)}
</select>

<ul>{municipios.slice(0, 20).map((m) => <li key={m.id}>{m.nome}</li>)}</ul>
O que a questão pede
Atualizar municípios automaticamente sempre que a UF selecionada for alterada.
Conceito cobrado
Efeito dependente de estado com useEffect e atualização reativa da interface.
Estrutura dos dados

A API devolve array de municípios com id e nome. Esse array deve ser substituído a cada troca de UF.

Como pensar
UF é estado de entrada; municípios é estado de resultado. Alterou UF, dispara fetch, atualiza lista.
Como validar
Ao trocar UF, os municípios mudam sem recarregar a página e sem manter dados da UF anterior.
Erro comum: esquecer uf na lista de dependências do useEffect e travar atualização.
EXERCÍCIO 13
Carregar lista de países (REST Countries)
Buscar e listar países com nome comum.
const [paises, setPaises] = useState([]);

async function carregarPaises() {
  const res = await fetch("https://restcountries.com/v3.1/all?fields=name,cca3,flags");
  const data = await res.json();
  const ordenados = data.sort((a, b) => a.name.common.localeCompare(b.name.common));
  setPaises(ordenados);
}

<button onClick={carregarPaises}>Carregar países</button>
<ul>
  {paises.slice(0, 30).map((p) => (
    <li key={p.cca3}>{p.name.common}</li>
  ))}
</ul>
O que a questão pede
Consultar todos os países, ordenar por nome comum e exibir em lista.
Conceito cobrado
Fetch + ordenação de coleção + renderização controlada por estado.
Estrutura dos dados

Use apenas os campos necessários: name, cca3 e flags. No endpoint /all, a documentação atual exige ?fields=....

Como pensar
Carregue bruto, ordene uma vez e renderize a versão já pronta para leitura.
Como validar
Após o clique, a lista deve aparecer em ordem alfabética; “Brazil” deve estar na posição coerente da ordenação.
Erro comum: usar nome como chave e gerar conflitos; prefira sempre cca3.
EXERCÍCIO 14
Selecionar país e exibir nome completo e bandeira
Combinar dropdown com exibição de metadados do país selecionado.
const [paisSelecionado, setPaisSelecionado] = useState("");
const pais = paises.find((p) => p.cca3 === paisSelecionado);

<select value={paisSelecionado} onChange={(e) => setPaisSelecionado(e.target.value)}>
  <option value="">Selecione</option>
  {paises.map((p) => (
    <option key={p.cca3} value={p.cca3}>{p.name.common}</option>
  ))}
</select>

{pais && (
  <div className="card">
    <h3>{pais.name.official}</h3>
    <img src={pais.flags.svg} alt={pais.name.common} width="220" />
  </div>
)}
O que a questão pede
Permitir seleção de país e mostrar nome oficial com bandeira do item escolhido.
Conceito cobrado
Busca de item selecionado com find e renderização condicional por estado.
Estrutura dos dados

Use cca3 para selecionar e campos name.official e flags.svg para exibir detalhes.

Como pensar
O select guarda apenas um identificador; os dados completos são recuperados do array já carregado.
Como validar
Ao mudar a opção, nome oficial e bandeira devem trocar juntos, sempre alinhados ao mesmo país.
Erro comum: guardar o objeto inteiro no value do select em vez de usar um identificador simples.
EXERCÍCIO 15
Carregar categorias de receitas (TheMealDB)
Listar categorias com botão de carregamento.
const [categorias, setCategorias] = useState([]);

async function carregarCategorias() {
  const res = await fetch("https://www.themealdb.com/api/json/v1/1/categories.php");
  const data = await res.json();
  setCategorias(data.categories || []);
}

<button onClick={carregarCategorias}>Carregar categorias</button>
<div className="grid">
  {categorias.map((c) => (
    <article key={c.idCategory} className="card">
      <h3>{c.strCategory}</h3>
      <img src={c.strCategoryThumb} alt={c.strCategory} width="220" />
      <p>{c.strCategoryDescription.slice(0, 140)}...</p>
    </article>
  ))}
</div>
O que a questão pede
Buscar categorias de receitas e exibir nome, imagem e descrição resumida.
Conceito cobrado
Integração com API externa e renderização de cards a partir de coleção remota.
Estrutura dos dados

Cada categoria chega em data.categories com idCategory, strCategory, strCategoryThumb e strCategoryDescription.

Como pensar
Carregue dados uma vez, normalize em estado e derive a apresentação dos cards sem duplicar fonte.
Como validar
Após o clique, os cards devem aparecer com imagem e texto; sem dados, a área deve permanecer vazia sem erro.
Erro comum: tentar mapear em undefined por não usar fallback data.categories || [].
EXERCÍCIO 16
Selecionar categoria e exibir descrição e imagem
Conectar seleção da categoria com detalhes visuais correspondentes.
const [categoriaSel, setCategoriaSel] = useState("");
const categoria = categorias.find((c) => c.idCategory === categoriaSel);

<select value={categoriaSel} onChange={(e) => setCategoriaSel(e.target.value)}>
  <option value="">Selecione</option>
  {categorias.map((c) => (
    <option key={c.idCategory} value={c.idCategory}>{c.strCategory}</option>
  ))}
</select>

{categoria ? (
  <article className="card">
    <h3>{categoria.strCategory}</h3>
    <img src={categoria.strCategoryThumb} alt={categoria.strCategory} width="260" />
    <p>{categoria.strCategoryDescription}</p>
  </article>
) : (
  <p>Selecione uma categoria para visualizar os detalhes.</p>
)}
O que a questão pede
Selecionar uma categoria da lista e mostrar detalhes completos do item escolhido.
Conceito cobrado
Estado de seleção + dado derivado com find + renderização condicional.
Estrutura dos dados

categoriaSel guarda o identificador; categoria é calculada a partir do array de categorias já carregado.

Como pensar
Mantenha uma única fonte de verdade no estado e derive o detalhe em tempo de renderização.
Como validar
Sem seleção, apenas mensagem neutra. Com seleção, nome, imagem e descrição devem refletir exatamente o item escolhido.
Erro comum: esquecer o estado vazio e tentar acessar propriedades de undefined antes da seleção.