memo, useMemo, useCallback
Implement or sketch code for memo, useMemo, useCallback. Explain the logic, complexity, and pros/cons of this approach.
Answers use simple, clear English.
Quick interview answer
Logic: React.memo skips re-render if props shallow-equal. useMemo caches computed value; useCallback caches function reference — helps memoized children avoid redundant renders.
Detailed answer
Logic: React.memo skips re-render if props shallow-equal. useMemo caches computed value; useCallback caches function reference — helps memoized children avoid redundant renders. Complexity notes included in code section when present. Pros: Targets expensive subtrees without manual shouldComponentUpdate. Cons: Premature optimization — memo has comparison cost; stale closures if deps wrong. Core: React.memo skips re-render if props shallow-equal. useMemo caches computed value; useCallback caches function reference — helps memoized children avoid redundant renders. Real-time example: Heavy DataGrid row component wrapped in memo; stable onSort callback via useCallback. Pros: Targets expensive subtrees without manual shouldComponentUpdate. Cons: Premature optimization — memo has comparison cost; stale closures if deps wrong. Common mistakes: Memoizing everything; useCallback with empty deps capturing changing state. Best practices: Profile first; memo leaf components receiving stable props from unstable parents. Audience level: Fresher.
Full explanation
React.memo skips re-render if props shallow-equal. useMemo caches computed value; useCallback caches function reference — helps memoized children avoid redundant renders.
Real example & use case
Heavy DataGrid row component wrapped in memo; stable onSort callback via useCallback.
Pros & cons
Pros: Targets expensive subtrees without manual shouldComponentUpdate. Cons: Premature optimization — memo has comparison cost; stale closures if deps wrong.
Code example
import { memo, useCallback, useMemo, useState } from 'react';
const Row = memo(function Row({ label, onPick }: { label: string; onPick: (l: string) => void }) {
return <button onClick={() => onPick(label)}>{label}</button>;
});
export function List({ items }: { items: string[] }) {
const [picked, setPicked] = useState<string | null>(null);
const onPick = useCallback((l: string) => setPicked(l), []);
const sorted = useMemo(() => [...items].sort(), [items]);
return sorted.map((i) => <Row key={i} label={i} onPick={onPick} />);
}Practice code · typescript (view only · no execution)
import { memo, useCallback, useMemo, useState } from 'react';
const Row = memo(function Row({ label, onPick }: { label: string; onPick: (l: string) => void }) {
return <button onClick={() => onPick(label)}>{label}</button>;
});
export function List({ items }: { items: string[] }) {
const [picked, setPicked] = useState<string | null>(null);
const onPick = useCallback((l: string) => setPicked(l), []);
const sorted = useMemo(() => [...items].sort(), [items]);
return sorted.map((i) => <Row key={i} label={i} onPick={onPick} />);
}Common mistakes
Memoizing everything; useCallback with empty deps capturing changing state.
Best practices
Profile first; memo leaf components receiving stable props from unstable parents.
Follow-up questions
Open one as its own read / solve / listen card