0Pricing
React Academy · Lesson

Typing Events & Refs in TypeScript

Use React.ChangeEvent, React.MouseEvent, and RefObject generics for DOM interactions.

Typing Events & Refs in TypeScript is a free React Academy lesson on CoddyKit — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the React Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

React Synthetic Events

React wraps native DOM events in SyntheticEvent. Each event type has a specific generic: React.ChangeEvent<HTMLInputElement>, React.MouseEvent<HTMLButtonElement>, etc.

Typing onChange

The most common event is onChange on inputs. Type its handler with React.ChangeEvent<HTMLInputElement>.

function SearchInput() {
  const [value, setValue] = useState('');

  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setValue(e.target.value);
  };

  return <input value={value} onChange={handleChange} />;
}

Typing onClick

Button clicks use React.MouseEvent<HTMLButtonElement>. Access e.currentTarget, e.preventDefault(), and e.stopPropagation() with full typing.

function DeleteButton({ onDelete }: { onDelete: () => void }) {
  const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
    e.stopPropagation();
    onDelete();
  };
  return <button onClick={handleClick}>Delete</button>;
}

Typing onSubmit

Form submission uses React.FormEvent<HTMLFormElement>. Always call e.preventDefault() to stop the default browser navigation.

function LoginForm() {
  const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    const form = e.currentTarget;
    const email = (form.elements.namedItem('email') as HTMLInputElement).value;
    console.log(email);
  };
  return (
    <form onSubmit={handleSubmit}>
      <input name="email" />
      <button type="submit">Login</button>
    </form>
  );
}

Typing Keyboard Events

Use React.KeyboardEvent<HTMLElement> to type keyboard handlers. Access e.key, e.code, and e.ctrlKey safely.

function CommandInput() {
  const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
    if (e.key === 'Enter' && e.metaKey) {
      submitCommand();
    }
  };
  return <input onKeyDown={handleKeyDown} />;
}

useRef for DOM Elements

Pass the HTML element type as the generic to useRef and initialize to null. TypeScript then knows the ref holds that element type.

function AutoFocusInput() {
  const inputRef = useRef<HTMLInputElement>(null);

  useEffect(() => {
    inputRef.current?.focus();
  }, []);

  return <input ref={inputRef} />;
}

Mutable Ref vs DOM Ref

When storing a mutable value (not a DOM node), initialize useRef with a value instead of null. TypeScript infers a mutable MutableRefObject.

// DOM ref (read-only current)
const divRef = useRef<HTMLDivElement>(null);

// Mutable ref (read-write current)
const countRef = useRef<number>(0);
countRef.current += 1; // ✓ no TypeScript error

Typing useImperativeHandle

When exposing a ref API from a child component, define an interface for the handle and use it in both forwardRef and useImperativeHandle.

interface DialogHandle {
  open: () => void;
  close: () => void;
}

const Dialog = forwardRef<DialogHandle, { title: string }>((props, ref) => {
  useImperativeHandle(ref, () => ({
    open: () => console.log('open'),
    close: () => console.log('close'),
  }));
  return <div>{props.title}</div>;
});

Ref Callbacks

A ref callback receives the DOM element or null. Type it as (node: HTMLElement | null) => void.

function MeasureDiv() {
  const [height, setHeight] = useState(0);

  const measuredRef = (node: HTMLDivElement | null) => {
    if (node) setHeight(node.getBoundingClientRect().height);
  };

  return <div ref={measuredRef}>Content: {height}px tall</div>;
}

Event Target vs Current Target

e.target is the element that triggered the event; e.currentTarget is the element the handler is attached to. Cast e.target when you need specific properties.

const handleClick = (e: React.MouseEvent<HTMLUListElement>) => {
  const target = e.target as HTMLLIElement;
  console.log(target.dataset.id);
};

Generic Event Handler Type

To write reusable event handler functions, use the generic React.EventHandler<Event> or just write the full function signature inline.

type InputChangeHandler = React.ChangeEventHandler<HTMLInputElement>;

const logChange: InputChangeHandler = (e) => {
  console.log(e.target.value); // e is fully typed
};

Quick Check

Which TypeScript type should you use for a useRef that holds an HTMLInputElement?

Recap

Type event handlers with React.ChangeEvent, React.MouseEvent, and React.FormEvent generics. Type DOM refs with useRef<HTMLElement>(null) and mutable refs with the value type. Use forwardRef with an explicit handle interface for imperative APIs.

Frequently asked questions

Is the “Typing Events & Refs in TypeScript” lesson free?

Yes — the full text of “Typing Events & Refs in TypeScript” is free to read here on the web, and the React Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the React Academy course, upgrade to CoddyKit PRO.

What will I learn in “Typing Events & Refs in TypeScript”?

Use React.ChangeEvent, React.MouseEvent, and RefObject generics for DOM interactions. You practise React Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start React Academy?

No prior experience is required. React Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Typing Events & Refs in TypeScript” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this React Academy lesson?

Yes. Every React Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Typing Props & Component Return Types
  2. Typing Events & Refs in TypeScript
  3. Generic Components & Utility Types
  4. Typing Context & Custom Hooks
← Back to React Academy