The “Before” (AI) code snippet to Audit/Fix:
useEffect(() => {
fetch(`/api/user/${id}`)
.then(res => res.json())
.then(data => setUser(data));
}, [id]);The “Dangling Fetch” (Race Condition)
useEffect(() => {
const controller = new AbortController();
const fetchData = async () => {
try {
const res = await fetch(`/api/user/${id}`, {
signal: controller.signal });
const data = await res.json();
setUser(data);
} catch (err) {
if (err.name !== 'AbortError') {
console.error(err);
}
}
};
fetchData();
return () => controller.abort(); // Cleanup
}, [id]);The “Before” (AI) code snippet to Audit/Fix:
function UserProfile({ user }: { user: any }) {
return <div>{user.profile.name}</div>;
}The “Lazy Type” (TypeScript Safety)
const UserProfile: React.FC<{ user: User }> = ({ user }) => {
// Guarding / Defensive Programming
if (!user.profile) return <p>No profile data available.</p>;
return <div>{user.profile.name}</div>;
}
~~~
The “Before” (AI) code snippet to Audit/Fix:
useEffect(() => {
const id = setInterval(() => {
setCount(count + 1);
}, 1000);
return () => clearInterval(id);
}, []);Stale State Closures
useEffect(() => {
const id = setInterval(() => {
setCount(prev => prev + 1); // Functional update avoids closure issue
}, 1000);
return () => clearInterval(id);
}, []);The “Before” (AI) code snippet to Audit/Fix:
const data = await response.json(); const user = data as User; console.log(user.profile.id);
The “Blind Cast” (Type Safety)
const data: unknown = await response.json();
// Type Guard for runtime safety
function isUser(data: any): data is User {
return data && typeof data.id === 'string' && 'profile' in data;
}
if (isUser(data)) {
console.log(data.profile.id);
} else {
throw new Error("Invalid API Response: Data does not match User schema");
}The “Before” (AI) code snippet to Audit/Fix:
function getFirstItem(items: any[]): any {
return items[0];
}
const item = getFirstItem([1, 2, 3]);The “Any” Generic (Reusability)
function getFirstItem<T>(items: T[]): T | undefined {
return items[0];
}
const item = getFirstItem([1, 2, 3]); // 'item' is correctly inferred as 'number'<T>), we allow TypeScript to perform ‘Type Inference.’ This ensures that if we pass a User[] into the function, we get a User out, preserving the full IDE autocomplete and type-checking benefits for the rest of the call stack.”
The “Before” (AI) code snippet to Audit/Fix:
const [data, setData] = useState<Data | null>(null);
useEffect(() => {
async function loadData() {
const response = await fetch('/api/data');
const result = await response.json();
setData(result); // Risk: If user leaves page, this crashes/leaks
}
loadData();
}, []);The “Ghost” State Update (Async Memory Leak)
setData(result); // Risk: If user leaves page, this crashes/leaks
useEffect(() => {
const controller = new AbortController();
(async () => {
try {
const response = await fetch('/api/data', { signal: controller.signal });
const result = await response.json();
setData(result);
} catch (err) {
if (err instanceof Error && err.name === 'AbortError') {
// Silent catch for intentional cancellation
return;
}
console.error("Fetch failed", err);
}
})();
return () => controller.abort(); // Correctly cancels the request
}, []);The “Before” (AI) code snippet to Audit/Fix:
const savedUser: User = JSON.parse(localStorage.getItem('user') || '{}');
return <div>{savedUser.name.toUpperCase()}</div>;The “Implicit Any” via JSON.parse
const savedUser: User = JSON.parse(localStorage.getItem('user') || '{}');
return <div>{savedUser.name.toUpperCase()}</div>; // Error if name is missing```
- The ("After") Fix: using the "Satisfies" or Guard pattern.
const rawData = localStorage.getItem(‘user’);
const parsedData: unknown = rawData ? JSON.parse(rawData) : null;
// Use a Type Guard to verify the shape before acting
function isValidUser(data: any): data is User {
return data && typeof data.name === ‘string’;
}
if (isValidUser(parsedData)) {
return <div>{parsedData.name.toUpperCase()}</div>;
}
return <div>Please log in.</div>;
~~~
The “Before” (AI) code snippet to Audit/Fix:
<div className="submit-btn" onClick={handleSubmit}>
Submit Form
</div>Semantic HTML & Accessibility (A11y)
<button
type="button"
className="submit-btn"
onClick={handleSubmit}
aria-label="Submit the registration form"
>
Submit Form
</button>What is the process of steps you should take when approaching an “Evaluator Audit”?
Logic Check: Does it actually work (race conditions, stale closures)?
Type Check: Is it safe (any/unknown, generics, narrowing)?
Performance Check: Are there wasted renders (memoization, unstable keys)?
Standards Check: A11y (ARIA), Security (XSS), and Readability.
Refactor & Justify: Write the fix and explain why (using PEEL: Point, Evidence, Explanation, Link).