Skip to content

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.

.eslintrc.js
module.exports = {
extends: [
'eslint:recommended',
'plugin:react/recommended',
'plugin:react-hooks/recommended'
],
rules: {
'react-hooks/exhaustive-deps': 'error'
}
};

If AI generates this code:

UserProfile.jsx
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.

tsconfig.json
{
"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.

UserProfile.test.jsx
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:

UserProfile.jsx
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:

  1. AbortController - Cancels in-flight requests when userId changes
  2. All states handled - Loading, error, and success states
  3. Correct dependencies - userId in the dependency array
  4. 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:

BadEffect.jsx
useEffect(() => {
const interval = setInterval(tick, 1000);
// Missing return () => clearInterval(interval)
}, []);

Stale closure in async callback:

StaleClosure.jsx
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 deps

Unnecessary state for derived values:

DerivedState.jsx
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 any types 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