React Expert Examples
Externalized from the agent definition per the few-shot-examples rule (#1587).
React Expert — Worked Examples
Externalized from the agent definition per the few-shot-examples rule (#1587).
Example 1: Component Architecture Review
Input: "Review our product listing page — it's slow and has a 6-second TTI"
Analysis approach:
# Check what's client-rendered that could be server-rendered
grep -r '"use client"' src/app/products/
# Check bundle contribution
npx next build --debug 2>&1 | grep "products"
Findings and fix:
// BEFORE: Entire page is a Client Component, blocking TTI
"use client";
import { useState, useEffect } from "react";
export default function ProductsPage() {
const [products, setProducts] = useState([]);
useEffect(() => {
fetch("/api/products").then(r => r.json()).then(setProducts);
}, []);
return <ProductGrid products={products} />;
}
// AFTER: Server Component fetches data, Client Component handles interactivity
// app/products/page.tsx — no "use client"
export default async function ProductsPage({
searchParams,
}: {
searchParams: { category?: string };
}) {
const products = await db.product.findMany({
where: { category: searchParams.category },
take: 24,
});
return (
<>
<CategoryFilter /> {/* Client Component */}
<Suspense fallback={<ProductGridSkeleton />}>
<ProductGrid products={products} /> {/* Server Component */}
</Suspense>
</>
);
}
Result: TTI drops from 6s to 1.2s by eliminating client-side data fetch waterfall.
Example 2: Performance Optimization — Unnecessary Re-renders
Input: "Our product list with 500 items is janky when the cart updates"
Diagnosis:
// React DevTools Profiler shows ProductCard re-renders 500 times on cart change
// Root cause: onAddToCart function reference changes every render
// BEFORE: new function reference every render
function ProductList({ products }) {
const [cart, setCart] = useState([]);
return products.map((p) => (
<ProductCard
key={p.id}
product={p}
// New function on every render → breaks memo
onAddToCart={(id) => setCart((prev) => [...prev, id])}
/>
));
}
// AFTER: stable references + memo
const ProductCard = memo(function ProductCard({ product, onAddToCart }) {
return (
<article>
<h2>{product.name}</h2>
<button onClick={() => onAddToCart(product.id)}>Add</button>
</article>
);
});
function ProductList({ products }) {
const [cart, setCart] = useState<string[]>([]);
const handleAddToCart = useCallback((id: string) => {
setCart((prev) => [...prev, id]);
}, []); // Stable: no deps change
return products.map((p) => (
<ProductCard key={p.id} product={p} onAddToCart={handleAddToCart} />
));
}
Result: Re-renders drop from 500 to 1 on cart update. Interaction latency under 16ms.
Example 3: Migration from Class Components to Hooks
Input: "Migrate our legacy class component with lifecycle methods to hooks"
// BEFORE: Class component with lifecycle methods
class UserProfile extends React.Component<Props, State> {
state = { user: null, loading: true, error: null };
componentDidMount() {
this.fetchUser();
}
componentDidUpdate(prevProps: Props) {
if (prevProps.userId !== this.props.userId) {
this.fetchUser();
}
}
componentWillUnmount() {
this.abortController?.abort();
}
fetchUser = async () => {
this.abortController = new AbortController();
try {
const user = await getUser(this.props.userId, this.abortController.signal);
this.setState({ user, loading: false });
} catch (err) {
if (err.name !== "AbortError") {
this.setState({ error: err, loading: false });
}
}
};
render() {
const { user, loading, error } = this.state;
if (loading) return <Spinner />;
if (error) return <ErrorMessage error={error} />;
return <UserCard user={user} />;
}
}
// AFTER: Functional component with hooks
function UserProfile({ userId }: Props) {
const [user, setUser] = useState<User | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<Error | null>(null);
useEffect(() => {
const controller = new AbortController();
setLoading(true);
setError(null);
getUser(userId, controller.signal)
.then((u) => { setUser(u); setLoading(false); })
.catch((err) => {
if (err.name !== "AbortError") {
setError(err);
setLoading(false);
}
});
return () => controller.abort(); // Cleanup on unmount or userId change
}, [userId]); // Re-runs when userId changes — replaces componentDidUpdate
if (loading) return <Spinner />;
if (error) return <ErrorMessage error={error} />;
if (!user) return null;
return <UserCard user={user} />;
}
// Better: extract to custom hook for reuse and testability
function useUser(userId: string) {
const [state, setState] = useState<{ user: User | null; loading: boolean; error: Error | null }>({
user: null, loading: true, error: null,
});
useEffect(() => {
const controller = new AbortController();
setState({ user: null, loading: true, error: null });
getUser(userId, controller.signal)
.then((user) => setState({ user, loading: false, error: null }))
.catch((error) => {
if (error.name !== "AbortError") {
setState({ user: null, loading: false, error });
}
});
return () => controller.abort();
}, [userId]);
return state;
}
function UserProfile({ userId }: Props) {
const { user, loading, error } = useUser(userId);
if (loading) return <Spinner />;
if (error) return <ErrorMessage error={error} />;
if (!user) return null;
return <UserCard user={user} />;
}