Когда ИИ ошибается тихо
Самые опасные баги от ИИ — те, которые НЕ выглядят как баги. Код компилируется, тесты проходят, локально всё ок. А в продакшне через неделю — упало. Это потому что ИИ хорошо имитирует «правильный» вид кода, но не проверяет его на тонкие сценарии.
Race conditions в useEffect
Классический паттерн: useEffect с fetch, зависимый от пропа. Если проп быстро меняется — запросы возвращаются в произвольном порядке. UI покажет данные старого запроса. Решение: AbortController или флаг отмены.
Забытые dependencies
useEffect (() => { ... }, []) — пустой массив зависимостей. ИИ часто пишет так чтобы «не вызывался лишний раз». Но если внутри используется prop или state — они не обновятся, эффект работает с устаревшими значениями.
SQL без параметризации
await db.query(
). Выглядит безобидно. Это SQL-инъекция. Если userId = "1; DROP TABLE users;" — таблица пропадает. Всегда параметризованные запросы.
Утечки памяти в подписках
addEventListener без removeEventListener в cleanup. setInterval без clearInterval. WebSocket без close. ИИ часто забывает уборку. Один компонент в порядке. 1000 компонентов — память течёт, страница тормозит.
// Тонкая ошибка от ИИ: race condition с useEffect.
// Этот код ВЫГЛЯДИТ нормально, но имеет баг.
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
useEffect(() => {
fetch(`/api/users/${userId}`)
.then((r) => r.json())
.then((data) => setUser(data));
}, [userId]);
if (!user) return <div>Загрузка...</div>;
return <div>{user.name}</div>;
}
// Что произойдёт если userId сменится с 1 на 2 быстро?
// Запрос за userId=1 может вернуться ПОСЛЕ запроса за userId=2.
// В итоге увидим данные пользователя 1, хотя выбран пользователь 2.Этот код — race condition. Запустите глазами с быстрым переключением userId.