Skip to main content
RapidDev - Software Development Agency
lovable-issues

Resolving ESLint Warnings and Errors in Lovable Code

ESLint warnings in Lovable-generated code come from unused variables, missing useEffect dependencies, React hooks rule violations, and implicit any types. Fix them by removing unused imports, completing dependency arrays, following the Rules of Hooks (never call hooks conditionally), and adding explicit TypeScript types. Prefix intentionally unused parameters with an underscore (_event) to suppress warnings without disabling the rule.

Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Advanced8 min read~15 minAll Lovable projects with ESLint configuredMarch 2026RapidDev Engineering Team
TL;DR

ESLint warnings in Lovable-generated code come from unused variables, missing useEffect dependencies, React hooks rule violations, and implicit any types. Fix them by removing unused imports, completing dependency arrays, following the Rules of Hooks (never call hooks conditionally), and adding explicit TypeScript types. Prefix intentionally unused parameters with an underscore (_event) to suppress warnings without disabling the rule.

Why ESLint warnings appear in Lovable-generated code

Lovable's AI generates functional code, but ESLint applies stricter standards than just 'works correctly.' The AI may declare variables it does not end up using, import components it later decides not to include, or write useEffect hooks with incomplete dependency arrays. These are not bugs that break your app, but they indicate code quality issues that can lead to real bugs later. The most impactful ESLint warnings in Lovable code are the React hooks rules. Calling a hook inside a conditional statement, a loop, or a nested function breaks React's internal state tracking and causes unpredictable behavior. The exhaustive-deps rule for useEffect prevents stale closure bugs that are among the hardest to debug. While it is tempting to disable ESLint rules that produce many warnings, most rules exist for good reasons. The better approach is to fix the warnings or, for intentionally unused parameters, use the underscore prefix convention to communicate intent.

  • Lovable generates import statements for components it does not end up using in the final code
  • useEffect dependency arrays are incomplete, triggering the exhaustive-deps rule
  • Hooks are called inside conditional blocks, violating the Rules of Hooks
  • TypeScript strict mode is not enabled, so implicit any types are widespread
  • Variables are declared in one generation step but the code that uses them is generated in a later step

Error messages you might see

'useState' is defined but never used

The component imports useState but never calls it. Either the AI generated an unused import, or the state was removed in a later edit. Delete the unused import.

React Hook useEffect has a missing dependency: 'fetchData'

The useEffect calls fetchData but it is not in the dependency array. Add fetchData to the array, or move the function definition inside the effect.

React Hook 'useState' is called conditionally. React Hooks must be called in the exact same order in every component render.

A useState or useEffect call is inside an if statement. Hooks must always be called at the top level of the component. Move the hook outside the conditional and use the condition inside the hook's logic.

'any' is not allowed as a type annotation

TypeScript's no-explicit-any rule is enabled. Replace 'any' with a specific type. If the type is unknown, use 'unknown' and narrow it with type guards.

Before you start

  • A Lovable project with ESLint warnings visible in Dev Mode or the browser console
  • Basic understanding of React hooks (useState, useEffect, useCallback)
  • Access to the Lovable editor for fixing the warnings

How to fix it

1

Remove unused variables and imports

Unused code adds clutter and can mask real issues — ESLint flags it to keep the codebase clean

Find all ESLint warnings about unused variables and imports. For each one, determine if the variable is truly unused or if it is needed but the code referencing it is missing. Delete imports that are not referenced anywhere in the file. For function parameters that are required by an interface but not used in your implementation, prefix them with an underscore: (_event) instead of (event).

Before
typescript
import { useState, useEffect, useCallback } from "react";
import { Button } from "@/components/ui/button";
import { Card } from "@/components/ui/card"; // Never used
const MyComponent = () => {
const [count, setCount] = useState(0); // count never read
const data = fetchData(); // data never used
return <Button>Click</Button>;
};
After
typescript
import { Button } from "@/components/ui/button";
// Removed: useState, useEffect, useCallback, Card (all unused)
const MyComponent = () => {
// Removed: unused count state and data variable
return <Button>Click</Button>;
};

Expected result: No more 'defined but never used' warnings. The code only contains imports and variables that are actually referenced.

2

Fix missing useEffect dependencies

Missing dependencies cause stale closures where the effect uses outdated values from a previous render

For each 'missing dependency' warning, add the missing variable to the dependency array. If adding it causes the effect to run too often, restructure: move functions inside the effect, wrap functions in useCallback, or use functional setState to avoid depending on the state variable.

Before
typescript
const [userId, setUserId] = useState("1");
const [data, setData] = useState(null);
// Warning: missing dependency 'userId'
useEffect(() => {
fetch(`/api/users/${userId}`).then(r => r.json()).then(setData);
}, []);
After
typescript
const [userId, setUserId] = useState("1");
const [data, setData] = useState(null);
// Fixed: userId in dependency array
useEffect(() => {
let cancelled = false;
fetch(`/api/users/${userId}`)
.then(r => r.json())
.then(d => { if (!cancelled) setData(d); });
return () => { cancelled = true; };
}, [userId]);

Expected result: No more exhaustive-deps warnings. The effect re-runs when userId changes and properly handles cleanup.

3

Fix React Hooks rule violations

Calling hooks conditionally breaks React's internal state tracking and causes unpredictable bugs

React requires that hooks are called in the exact same order on every render. If a hook is inside an if statement, it only runs on some renders, breaking this rule. Move the hook to the top level and put the conditional logic inside the hook's callback or after the hook call. This is a hard rule — there is no workaround other than restructuring the code.

Before
typescript
const MyComponent = ({ showCounter }: { showCounter: boolean }) => {
// Error: hook called conditionally
if (showCounter) {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>{count}</button>;
}
return <p>No counter</p>;
};
After
typescript
const MyComponent = ({ showCounter }: { showCounter: boolean }) => {
// Fixed: hook always called at top level
const [count, setCount] = useState(0);
if (!showCounter) {
return <p>No counter</p>;
}
return <button onClick={() => setCount((prev) => prev + 1)}>{count}</button>;
};

Expected result: No more 'hooks called conditionally' error. The hook is always called, and the conditional logic is below it.

4

Replace any types with specific TypeScript types

Explicit types catch bugs at compile time and make the code self-documenting

Find all instances of the any type and replace them with specific types. For API responses, define an interface. For event handlers, use React's built-in types like React.ChangeEvent<HTMLInputElement>. For truly unknown data, use the unknown type with type guards to narrow it safely. If fixing types across a large generated codebase involves understanding complex type hierarchies, RapidDev's engineers have done this across 600+ Lovable projects.

Before
typescript
const handleSubmit = (data: any) => {
const result: any = processData(data);
setItems(result.items as any[]);
};
After
typescript
type FormData = {
name: string;
email: string;
};
type ProcessResult = {
items: string[];
total: number;
};
const handleSubmit = (data: FormData) => {
const result: ProcessResult = processData(data);
setItems(result.items);
};

Expected result: No more 'any' type warnings. TypeScript can now catch type errors at compile time.

Complete code example

src/components/CleanComponent.tsx
1import { useState, useEffect } from "react";
2import { Button } from "@/components/ui/button";
3
4// Specific type instead of 'any'
5type User = {
6 id: string;
7 name: string;
8 email: string;
9};
10
11type CleanComponentProps = {
12 userId: string;
13 onSelect?: (user: User) => void;
14};
15
16const CleanComponent = ({ userId, onSelect }: CleanComponentProps) => {
17 const [user, setUser] = useState<User | null>(null);
18 const [loading, setLoading] = useState(true);
19
20 // All dependencies included, cleanup function present
21 useEffect(() => {
22 let cancelled = false;
23 setLoading(true);
24
25 fetch(`/api/users/${userId}`)
26 .then((res) => res.json())
27 .then((data: User) => {
28 if (!cancelled) {
29 setUser(data);
30 setLoading(false);
31 }
32 })
33 .catch(() => {
34 if (!cancelled) setLoading(false);
35 });
36
37 return () => { cancelled = true; };
38 }, [userId]); // userId is the only dependency
39
40 // Intentionally unused parameter prefixed with _
41 const handleKeyDown = (_event: React.KeyboardEvent) => {
42 // Handler structure needed for accessibility
43 };
44
45 if (loading) return <p>Loading...</p>;
46 if (!user) return <p>User not found</p>;
47
48 return (
49 <div className="space-y-4" onKeyDown={handleKeyDown}>
50 <h2 className="text-xl font-bold">{user.name}</h2>
51 <p className="text-muted-foreground">{user.email}</p>
52 {onSelect && (
53 <Button onClick={() => onSelect(user)}>Select User</Button>
54 )}
55 </div>
56 );
57};
58
59export default CleanComponent;

Best practices to prevent this

  • Remove unused imports and variables immediately — they accumulate quickly in AI-generated code
  • Never suppress the exhaustive-deps ESLint warning — fix the dependency issue instead
  • Prefix intentionally unused parameters with underscore (_event, _index) to suppress warnings without disabling rules
  • Always call React hooks at the top level of the component — never inside conditionals, loops, or nested functions
  • Define TypeScript types for all function parameters and return values instead of using any
  • Use the unknown type instead of any when the type is genuinely unknown — it forces type narrowing
  • Configure ESLint rules as warnings during development and errors in production builds
  • Ask Lovable to fix ESLint warnings as a dedicated prompt rather than mixing with feature requests

Still stuck?

Copy one of these prompts to get a personalized, step-by-step explanation.

ChatGPT Prompt

My Lovable project has many ESLint warnings. Here is a component with several issues: [paste your component code here] Please: 1. Remove all unused imports and variables 2. Fix missing useEffect dependencies 3. Fix any hooks called conditionally 4. Replace all 'any' types with specific TypeScript types 5. Prefix intentionally unused parameters with underscore 6. Add proper cleanup functions to useEffect hooks

Lovable Prompt

Fix all ESLint warnings in @src/components/Dashboard.tsx. Remove unused imports and variables. Add missing dependencies to all useEffect hooks. Fix any hooks that are called conditionally by moving them to the top level. Replace all 'any' types with specific TypeScript interfaces. Prefix intentionally unused parameters with an underscore. Do not change any functionality — only fix code quality warnings.

Frequently asked questions

Why does Lovable generate code with ESLint warnings?

Lovable's AI focuses on making functional code quickly. It may import components it does not end up using, leave dependency arrays incomplete, or use any types for speed. These do not break the app but reduce code quality. Fix them as a separate cleanup step.

How do I fix the 'missing dependency' warning in useEffect?

Add the missing variable to the dependency array. If that causes the effect to run too often, restructure: move functions inside the effect, wrap them in useCallback, or use functional setState to avoid depending on the state variable directly.

Can I disable ESLint rules I do not agree with?

You can, but most React-specific rules exist to prevent real bugs. The exhaustive-deps and hooks rules are particularly important. If you must disable a rule, use eslint-disable-next-line with a comment explaining why, not a blanket rule-off.

How do I handle unused function parameters?

If a parameter is required by a type or interface but not used in your implementation, prefix it with an underscore: (_event, _index, _unused). This tells ESLint the omission is intentional. Configure the rule: @typescript-eslint/no-unused-vars with argsIgnorePattern: '^_'.

Should I fix ESLint warnings or build features first?

Build features first, then fix warnings as a cleanup step. ESLint warnings do not break functionality. However, do not let warnings accumulate too long — the exhaustive-deps warnings in particular can mask real stale state bugs.

What if I can't fix this myself?

If your project has many ESLint errors across dozens of files and fixing them requires understanding TypeScript types and React hook rules, RapidDev's engineers can clean up the entire codebase. They have resolved ESLint issues across 600+ Lovable projects.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your issue.

Book a free consultation

Need help with your Lovable project?

Our experts have built 600+ apps and can solve your issue fast. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.