Почему массив пустой — и почему при этом нет ошибки

Симптом знакомый до боли: экран пустой, данные в базе точно есть, а в консоли []. И — ничего. Ни красной строки, ни предупреждения. Тишина.
Вот главное, что нужно понять: это не ошибка, а ответ. Код отработал безупречно и честно сообщил, что подходящих записей ноль. Поэтому ничего и не падает — ломать было нечего. Причин у такого ответа ровно три, и первая встречается чаще двух остальных вместе.
Причина 1. Данные ещё не пришли
Самая частая. Запрос к серверу асинхронный: страница рисуется мгновенно, а ответ приходит через доли секунды. В этот зазор массив пуст по-настоящему — данных ещё физически нет.
Как проверить. Поставь лог прямо перед тем местом, где читаешь список:
console.log("items:", items.length, items)
Открой логи. Если строка напечаталась дважды — сначала 0, потом 12 — диагноз готов: данные приходят, просто позже, чем ты их смотришь. Один-единственный 0 означает, что проблема в другом месте, иди к причине 2.
Как починить. Не делай выводов на первом проходе. Заведи отдельное состояние загрузки и показывай спиннер, пока ответ не пришёл; «ничего не найдено» пиши только после того, как ответ получен. Если список собираешь в цикле с запросами — убедись, что каждый запрос дождались через await, а не запустили пачкой и помчались дальше.
Практический промпт, который закрывает это сразу: «добавь три состояния — загрузка, пустой список, список с данными». ИИ почти всегда пишет только третье.
Причина 2. Фильтр отрезал всё
Данные дошли, но до экрана не добрались: условие не совпало ни разу. Выглядит одинаково — [] без ошибок.
Классика жанра — типы. Строка и число не равны друг другу при строгом сравнении:
"5" === 5 // false
items.filter(i => i.categoryId === selectedId)
Если selectedId приехал из адресной строки или из поля формы, он строка, а в данных лежит число. Совпадений ноль. Рядом живут родственники: лишний пробел в значении и разный регистр — «Алматы» и «алматы» для кода два разных города.
Как проверить. Временно выключи фильтр и посмотри длину. Вернулись данные — виноват он. Дальше выведи оба значения вместе с типами:
console.log(typeof i.categoryId, i.categoryId, typeof selectedId, selectedId)
Разные типы в одной строке видно сразу.
Как починить. Приведи к одному типу перед сравнением (Number(selectedId)), а текст — к одному регистру и без пробелов по краям (value.trim().toLowerCase()). Сравнивать «как есть» можно только внутри своих данных, где ты контролируешь формат.
Причина 3. Список лежит глубже, чем ты смотришь
Ответ сервера пришёл целиком, но список внутри него — не на верхнем уровне. Почти все API заворачивают данные:
{ "data": { "items": [ ... ], "total": 42 } }
Ты читаешь response.data, а список лежит в response.data.items. Результат — пусто, и снова без ошибки, потому что обращение к несуществующему полю в JavaScript просто даёт undefined.
Как проверить. Выведи весь ответ целиком, не разбирая его на ходу: console.log(JSON.stringify(response, null, 2)). Посмотри глазами, где именно начинаются квадратные скобки — это и есть твой массив.
Как починить. Возьми правильный путь до списка. И на будущее — заведи привычку смотреть сырой ответ первым делом, до всякой обработки. Если в логе вместо структуры совсем пусто, ты, скорее всего, имеешь дело с соседней бедой: fetch вернул undefined — там запрос не дошёл вовсе, а тут дошёл, просто читают не тот ключ.
Порядок действий, если лень разбираться
Три лога в трёх точках, сверху вниз — сырой ответ, список сразу после разбора, список после фильтра. Место, где длина превращается в ноль, и есть твоя причина. Минута работы, и гадать больше не о чем.
Почему нет ошибки, если данных нет?
Потому что «ноль записей» — допустимый результат. Пустой поиск, новый пользователь без заказов, чистый чат — во всех случаях код должен показать пустой экран, а не упасть. Ошибку стоит ждать только когда сломался сам запрос.
Массив пустой или это undefined?
Это разные диагнозы, и проверяются по-разному. [] в логе означает «список есть, в нём ноль элементов» — иди по трём причинам выше. undefined означает, что списка нет вовсе: переменная не заполнилась, ключ назван не так или запрос не дошёл.
Короткие уроки-истории, симулятор агента и ежедневная практика — в нашем мобильном приложении. Бесплатно.





