How to Verify AI-Generated React Code is Correct
I asked ChatGPT to write a React component. It gave me code that looked perfect. I pasted it into my project. No errors. I thought I was done.
I was wrong.
The component had a race condition. It would fail if props changed quickly. But since it worked in my initial test, I assumed it was correct. This is the core problem with AI-generated code: it often passes superficial checks but contains subtle bugs.
The Real Problem
AI-generated React code has a specific issue. The code looks syntactically correct. It might even run without errors. But it can contain:
- Stale closures in async callbacks
- Missing cleanup in effects
- Incorrect dependency arrays
- Memory leaks
- Security vulnerabilities
A Reddit discussion about “React Viber Coders” highlights this. One comment with 9 points says: “The core issue is that models can’t say when they’re unsure or don’t know. The hallucinations pass the tests but are often just forcefully slammed together.”
Another developer noted: “You can get quality output if you’re knowledgeable enough to give quality input and review the output for at least moderate accuracy.”
The “placebo effect” is real. Developers believe code is correct just because AI generated it. This is dangerous.
How I Verify AI Code Now
I use a multi-layer verification approach. Each layer catches different types of problems.
Layer 1: ESLint with React Hooks Rules
First, I run ESLint with the React hooks plugin. This catches dependency array issues.
module.exports = { extends: [ 'eslint:recommended', 'plugin:react/recommended', 'plugin:react-hooks/recommended' ], rules: { 'react-hooks/exhaustive-deps': 'error' }};If AI generates this code:
function UserProfile({ userId }) { const [user, setUser] = useState(null); useEffect(() => { fetchUser(userId).then(data => setUser(data)); }, []); // ESLint will warn about missing userId return <div>{user?.name}</div>;}ESLint catches the missing userId dependency. The AI might forget this. The linter won’t.
Layer 2: TypeScript Strict Mode
I enable strict TypeScript checks. This catches type mismatches and null safety issues.
{ "compilerOptions": { "strict": true, "noUncheckedIndexedAccess": true, "noImplicitReturns": true }}AI often generates code with implicit any types or assumes properties exist. TypeScript strict mode forces me to handle edge cases.
Layer 3: React Testing Library
I write tests for critical user flows. AI-generated code often passes “it renders” tests but fails “it works correctly” tests.
import { render, screen, waitFor } from '@testing-library/react';import userEvent from '@testing-library/user-event';
test('handles rapid userId changes without race conditions', async () => { const user = userEvent.setup();
render(<UserProfile userId="1" />);
// Simulate rapid prop changes rerender(<UserProfile userId="2" />); rerender(<UserProfile userId="3" />);
await waitFor(() => { expect(screen.getByText(/loading/i)).not.toBeInTheDocument(); });
// Should show user 3, not user 1 or 2 expect(screen.getByText('User 3')).toBeInTheDocument();});This test would catch the race condition in the buggy version.
Layer 4: React DevTools Inspection
I use React DevTools to inspect component behavior. I check:
- Re-render frequency (unnecessary re-renders)
- Effect cleanup (memory leaks)
- State updates (infinite loops)
Open DevTools, go to the Profiler tab, and record interactions. Watch for components that re-render without reason.
The Corrected Code
Here is the fixed version of the UserProfile component:
import { useState, useEffect } from 'react';
function UserProfile({ userId }) { const [user, setUser] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null);
useEffect(() => { const controller = new AbortController();
setLoading(true); setError(null);
fetchUser(userId, { signal: controller.signal }) .then(data => { setUser(data); setLoading(false); }) .catch(err => { if (err.name !== 'AbortError') { setError(err.message); setLoading(false); } });
return () => controller.abort(); }, [userId]);
if (loading) return <div>Loading...</div>; if (error) return <div>Error: {error}</div>; return <div>{user?.name}</div>;}Key improvements:
- AbortController - Cancels in-flight requests when
userIdchanges - All states handled - Loading, error, and success states
- Correct dependencies -
userIdin the dependency array - Cleanup function - Returns cleanup to prevent memory leaks
Common AI Mistakes I See
I’ve noticed patterns in AI-generated React code:
Missing cleanup in effects:
useEffect(() => { const interval = setInterval(tick, 1000); // Missing return () => clearInterval(interval)}, []);Stale closure in async callback:
const [count, setCount] = useState(0);useEffect(() => { const id = setInterval(() => { console.log(count); // Always logs 0, even after updates }, 1000); return () => clearInterval(id);}, []); // count should be in depsUnnecessary state for derived values:
const [fullName, setFullName] = useState('');useEffect(() => { setFullName(`${firstName} ${lastName}`);}, [firstName, lastName]);// Just use: const fullName = `${firstName} ${lastName}`;My Verification Checklist
Before I accept any AI-generated code:
- ESLint passes with no warnings
- TypeScript compiles with strict mode
- Tests cover happy path and edge cases
- DevTools shows expected re-renders
- Effect cleanup is present
- Dependencies are correct
- No
anytypes without justification - Error states are handled
The Key Insight
You cannot verify code you don’t understand. AI can generate working code. But you must know enough React to spot when it’s wrong.
The Reddit commenter was right: quality output requires quality review. If I can’t explain why the code works, I shouldn’t ship it.
In this post, I showed you my verification process for AI-generated React code. The tools (ESLint, TypeScript, Testing Library, DevTools) help. But the most important tool is understanding React fundamentals. Without that, I’m just trusting AI blindly. And that’s not verification at all.
Final Words + More Resources
My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me
Here are also the most important links from this article along with some further resources that will help you in this scope:
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments