🌐 Detecting your location…

Como corrigir o erro ‘Não é possível ler propriedades de indefinido’ em JavaScript

⏱️7 min read  ·  1,512 words

TypeError: Cannot read properties of undefined (reading 'x')é o erro de tempo de execução mais comum em JavaScript. A mensagem é precisa quando você aprende a lê-la, e a correção é quase sempre um dos cinco padrões. Este guia aborda como localizar a causa rapidamente e como evitar que ela se repita.

O que o erro realmente significa

Você tentou ler uma propriedade de algo que éundefined. A parte entre parênteses informa qual propriedade você tentou ler.

const user = undefined;
console.log(user.name);
// TypeError: Cannot read properties of undefined (reading 'name')

A visão crítica:o problema não é a propriedade, é a coisa antes do ponto. Quando você vê(reading 'name'), o bug é que tudo o que deveria conter o objeto do usuário éundefined. Todo mundo perde tempo depurandoname quando eles deveriam estar perguntando por quêuser está vazio.

Em uma corrente, trabalhe da esquerda para a direita para encontrar o primeiro elo indefinido.

const response = { data: { items: [] } };
console.log(response.data.results.length);
// TypeError: Cannot read properties of undefined (reading 'length')
// 'results' does not exist on data, so response.data.results is undefined.

Causa 1: dados assíncronos lidos antes de chegarem

De longe a causa mais frequente em aplicações reais. O estado começa vazio, a renderização é executada e a busca ainda não foi resolvida.

function Profile({ userId }) {
  const [user, setUser] = useState();   // undefined on first render

  useEffect(() => {
    fetch(`/api/users/${userId}`)
      .then(r => r.json())
      .then(setUser);
  }, [userId]);

  return <h1>{user.name}</h1>;   // throws on the very first render
}

Corrija inicializando com um valor vazio sensato e protegendo a renderização.

function Profile({ userId }) {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    let cancelled = false;
    setLoading(true);

    fetch(`/api/users/${userId}`)
      .then(r => {
        if (!r.ok) throw new Error(`HTTP ${r.status}`);
        return r.json();
      })
      .then(data => { if (!cancelled) setUser(data); })
      .catch(err => { if (!cancelled) console.error(err); })
      .finally(() => { if (!cancelled) setLoading(false); });

    return () => { cancelled = true; };
  }, [userId]);

  if (loading) return <p>Loading…</p>;
  if (!user)   return <p>User not found.</p>;

  return <h1>{user.name}</h1>;
}

Ocancelled flag também evita um segundo bug comum: uma resposta lenta de umuserId substituindo os dados mais recentes após a alteração do suporte.

Causa 2: o formato da resposta da API não é o que você presumiu

Você escreveudata.items mas a API retorna{ results: [...] }, ou envolve tudo em{ data: { ... } }. É especialmente fácil errar com o Axios, que adiciona seu própriodata wrapper na parte superior do corpo da resposta.

// Axios puts the response body in .data — so the payload is often data.data
const response = await axios.get('/api/users');
console.log(response.data.users);     // correct
console.log(response.users);          // undefined -> throws downstream

Registre toda a resposta antes de indexá-la. Umconsole.log(JSON.stringify(response, null, 2)) responde à pergunta imediatamente, onde a adivinhação não.

Causa 3: métodos de pesquisa de array que não encontraram nada

find retornaundefined quando nenhum elemento corresponde, e esta é a fonte mais comum do erro no código de manipulação de lista.

const users = [{ id: 1, name: 'Ada' }];
const match = users.find(u => u.id === 99);
console.log(match.name);
// TypeError: Cannot read properties of undefined (reading 'name')

Sempre trate o resultado como possivelmente ausente.

const match = users.find(u => u.id === 99);
if (!match) {
  return null;               // or throw a clear domain error
}
console.log(match.name);

// Or with optional chaining when a missing value is acceptable:
console.log(match?.name ?? 'Unknown user');

O mesmo se aplica adocument.querySelector, que retornanull quando nada corresponde, e paraMap.get eArray.at.

Causa 4: Desestruturando um objeto indefinido

A desestruturação lê propriedades, então é lançada exatamente pelo mesmo motivo – apenas com uma linha de pilha menos óbvia.

function greet({ name }) {
  return `Hello ${name}`;
}
greet();
// TypeError: Cannot destructure property 'name' of 'undefined'

Dê um padrão ao parâmetro para que a desestrutura sempre tenha um objeto com o qual trabalhar.

function greet({ name = 'friend' } = {}) {
  return `Hello ${name}`;
}
greet();               // "Hello friend"
greet({ name: 'Ada' }); // "Hello Ada"

Causa 5:this Perdeu a ligação

Quando um método é passado como retorno de chamada,this não é mais o objeto, portanto, todas as propriedades lidas nele falham.

class Counter {
  constructor() { this.count = 0; }
  increment() { this.count++; }   // 'this' is undefined when detached
}

const c = new Counter();
button.addEventListener('click', c.increment);
// TypeError: Cannot read properties of undefined (reading 'count')

Vincule-o ou use um campo de classe com uma função de seta, que capturathis lexicalmente.

class Counter {
  count = 0;
  increment = () => { this.count++; };   // arrow field — always bound
}

const c = new Counter();
button.addEventListener('click', c.increment);   // works

As ferramentas que o impedem

Encadeamento opcional curto-circuitos paraundefined em vez de jogar.

const city = user?.address?.city;              // undefined, no throw
const first = users?.[0]?.name;                // works on arrays too
const result = api.getUser?.(id);              // and on possibly-missing methods

Coalescência nula fornece um substituto apenas paranull eundefined, ao contrário de|| que também substitui0 e strings vazias.

const count = data?.count ?? 0;      // 0 stays 0
const wrong = data?.count || 0;      // a real 0 becomes 0 anyway, but '' becomes 0 too

Use encadeamento opcional onde um valor ausente for genuinamente válido. Não espalhe-o por toda parte para silenciar erros – seuser deve sempre existir nesse ponto, ocultar sua ausência transforma um bug barulhento em um bug silencioso que surge mais tarde sem nenhum rastreamento de pilha.

Método de depuração

Quando o erro aparecer, siga esta sequência.

  1. Leia o nome da propriedade entre parênteses. O bug está na expressãoantes aquela propriedade.
  2. Abra o rastreamento de pilha e clique no quadro superior do seu próprio código, ignorando os quadros da biblioteca.
  3. Defina um ponto de interrupção nessa linha e inspecione a expressão que contém, não a propriedade.
  4. Percorra a corrente da esquerda para a direita para encontrar o primeiro elo indefinido.
  5. Pergunte por que esse valor está vazio – uma busca não foi resolvida, uma pesquisa falhou, um suporte nunca foi aprovado?

Na produção, os mapas de origem são essenciais. Sem eles, o rastreamento aponta para o código minificado e esse processo é impossível.

Prevenindo Estruturalmente

Datilografado captura a maioria deles em tempo de compilação, especialmente comstrictNullChecks habilitado. Isso força você a lidar com o caso indefinido antes da execução do código.

function getName(user: User | undefined): string {
  // Error: 'user' is possibly 'undefined' — caught before runtime
  return user.name;
}

Valide nos limites. Analise as respostas da API com um validador de esquema como Zod para que uma forma inesperada falhe imediatamente com uma mensagem clara, em vez de propagar três camadas indefinidas em seu código de renderização.

Retorna coleções vazias, não indefinidas. Uma função que retorna[] em vez deundefined permite que os chamadores mapeiem o resultado incondicionalmente.

Perguntas Frequentes

P: Qual é a diferença entre isso e “Não é possível ler propriedades de nulo”?
R: Somente o valor. undefined geralmente significa que uma variável nunca foi atribuída ou que uma propriedade não existe; null geralmente significa algo explicitamente definido como vazio. A abordagem de depuração é idêntica.

P: Devo apenas adicionar encadeamento opcional em todos os lugares?
R: Não. Use-o onde um valor for legitimamente opcional. Usá-lo para silenciar um erro que você não entende converte uma falha com rastreamento de pilha em um comportamento errado sem nenhum rastreamento.

P: Por que funciona localmente, mas falha na produção?
R: Geralmente tempo ou dados. As APIs locais respondem mais rapidamente, ocultando as condições de corrida; e os dados de produção contêm formas que seus dados de teste não contêm, como registros com campos opcionais ausentes.

P: Como encontro o erro quando o rastreamento de pilha mostra apenas o código da biblioteca?
R: Habilite os mapas de origem e use a “Lista de ignorados” no Chrome DevTools para ocultar os quadros da estrutura para que o quadro visível mais alto seja seu próprio código.

P: O TypeScript elimina esse erro completamente?
R: Não. Ele elimina o código que pode verificar, mas os dados ultrapassam os limites do tempo de execução — respostas da API, análise JSON,any casts — ainda pode ser indefinido em tempo de execução. Valide dados externos mesmo em TypeScript.

Conclusão

CorreçãoCannot read properties of undefined é mecânico quando você conhece a regra:o erro está na expressão antes da propriedade, não na propriedade em si. Verifique as cinco causas comuns: leitura de dados assíncronos muito cedo, formato de API incompatível,find que não correspondia a nada, desestruturando um objeto ausente e um objeto perdidothis vinculativo. Em seguida, evite a recorrência com encadeamento opcional onde os valores são genuinamente opcionais, TypeScript comstrictNullCheckse validação de esquema em cada limite onde dados externos entram em seu sistema.

MD Rafikul Islam

Written by

MD Rafikul Islam is a software developer and the editor of TechPulse. He writes about developer tooling, hardware, and the practical decisions that come up in day-to-day engineering work — which laptop to buy, which framework to commit to, why a build broke at 2am. He tests the tools he writes about and says plainly when something is not worth the money. Corrections and corrections requests are welcome at rony.yf25@gmail.com.

✍️ Leave a Comment

Your email address will not be published. Required fields are marked *

🌐 Read in:🇬🇧 English🇩🇪 Deutsch🇧🇷 Português🇸🇦 العربية🇮🇳 हिन्दी🇧🇩 বাংলা