All skills
asyrafhussin avatar

/typescript-react-patterns

@e60e907

TypeScript best practices for React development. Use when writing typed React components, hooks, events, refs, or generic components. Triggers on tasks involving TypeScript errors, type definitions, props typing, or type-safe React patterns.

Use this Skill: https://skilld.dev/gh/asyrafhussin/agent-skills/typescript-react-patterns

This session only. Nothing lands on disk.

rulesref-callback.md

≈846 tokens on demand. Your agent reads this file only when SKILL.md points to it.

Callback Ref Pattern

Impact: HIGH (eliminates extra render cycles for DOM measurement)

Callback refs fire the moment a DOM node is attached or detached. This avoids the extra render cycle caused by useRef + useEffect when you need to measure or interact with a DOM element immediately.

Incorrect

// ❌ Bad
function MeasuredBox() {
  const boxRef = useRef<HTMLDivElement>(null);
  const [height, setHeight] = useState(0);

  // Extra render cycle: component renders → ref attaches → effect runs → state updates → re-render
  useEffect(() => {
    if (boxRef.current) {
      setHeight(boxRef.current.getBoundingClientRect().height);
    }
  }, []);

  return (
    <div>
      <div ref={boxRef}>Content that needs measuring</div>
      <p>Height: {height}px</p>
    </div>
  );
}

Problems:

  • useEffect runs after paint, causing a visible flash when height updates
  • Requires an extra render cycle: mount, then measure, then re-render with measurement
  • Does not react to the element being conditionally shown/hidden
  • If the element mounts later (e.g., after data loads), the effect won't re-run

Correct

// ✅ Good
function MeasuredBox() {
  const [height, setHeight] = useState(0);

  // Callback ref — fires immediately when the DOM node attaches
  const measuredRef = useCallback((node: HTMLDivElement | null) => {
    if (node !== null) {
      setHeight(node.getBoundingClientRect().height);
    }
  }, []);

  return (
    <div>
      <div ref={measuredRef}>Content that needs measuring</div>
      <p>Height: {height}px</p>
    </div>
  );
}

// Callback ref for conditional elements
function Tooltip({ show, text }: { show: boolean; text: string }) {
  const [position, setPosition] = useState({ top: 0, left: 0 });

  const tooltipRef = useCallback((node: HTMLDivElement | null) => {
    if (node) {
      const rect = node.getBoundingClientRect();
      setPosition({
        top: rect.top - rect.height - 8,
        left: rect.left + rect.width / 2,
      });
    }
  }, []);

  if (!show) return null;

  // Callback ref fires each time this element mounts
  return (
    <div ref={tooltipRef} style={{ position: "fixed", ...position }}>
      {text}
    </div>
  );
}

// Callback ref with cleanup (React 19+)
function ResizeObserverBox() {
  const [width, setWidth] = useState(0);

  const observerRef = useCallback((node: HTMLDivElement | null) => {
    if (node) {
      const observer = new ResizeObserver(([entry]) => {
        setWidth(entry.contentRect.width);
      });
      observer.observe(node);

      // Return cleanup function (React 19+)
      return () => observer.disconnect();
    }
  }, []);

  return (
    <div ref={observerRef}>
      <p>Width: {width}px</p>
    </div>
  );
}

Benefits:

  • No extra render cycle — measurement happens the instant the node attaches
  • Automatically fires when conditionally rendered elements mount or unmount
  • Works with elements that appear after async data loads
  • Cleanup function support (React 19+) enables attaching observers cleanly

Reference: React TypeScript Cheatsheet — useRef

Source: SKILL.md on GitHub

No alerts16d5 checks · Risk SAFE
  • Gen Agent Trust Hub16d

    The skill contains educational reference material and code documentation for TypeScript React development patterns. No security risks or malicious vectors were detected.

  • Socket16d

    No alerts

  • Snyk16d

    Risk: LOW · No issues

  • Runlayer6mo

    30 files scanned · No issues

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at e60e907. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub last month.

Steadyupdated 7 months ago
metadata
{
  "author": "agent-skills",
  "version": "2.0.0"
}

README badge

README badge for asyrafhussin/agent-skills/typescript-react-patterns