← Back to the Build Your Homepage series
πŸ”·
EPISODE 06
Component props Β· useState Β· useEffect Β· events

TypeScript + React

Type your React components properly: props, state, refs, and event handlers. Just enough TypeScript to make React feel like a proper language.

ReactTypeScriptpropsuseStateevents
Duration
⏱ About 2 hours
Level
πŸ“Š Intermediate+
Prerequisite
🎯 ts-05 + React basics
OUTCOME
A fully typed React component with no any anywhere

What you'll learn

  • 1Type component props with type or interface
  • 2Type useState and useReducer
  • 3Type event handlers correctly
  • 4Use children: React.ReactNode and forwardRef

1. Typed Props

tsx
type ButtonProps = {
  label: string;
  onClick: () => void;
  variant?: "primary" | "secondary";
  children?: React.ReactNode;
};

function Button({ label, onClick, variant = "primary", children }: ButtonProps) {
  return (
    <button className={`btn btn-${variant}`} onClick={onClick}>
      {label}
      {children}
    </button>
  );
}

2. useState

tsx
// Usually inferred:
const [count, setCount] = useState(0);            // number

// Explicit when the initial value does not tell the full story:
const [user, setUser] = useState<User | null>(null);
const [items, setItems] = useState<string[]>([]);

3. Event Handlers

tsx
function Form() {
  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    console.log(e.target.value);
  };
  const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
  };
  return (
    <form onSubmit={handleSubmit}>
      <input onChange={handleChange} />
    </form>
  );
}

4. Refs and Custom Hooks

tsx
function AutoFocus() {
  const ref = useRef<HTMLInputElement>(null);
  useEffect(() => { ref.current?.focus(); }, []);
  return <input ref={ref} />;
}

function useToggle(initial = false): [boolean, () => void] {
  const [on, setOn] = useState(initial);
  return [on, () => setOn(v => !v)];
}
Example code / lecture materials

All lecture materials and example code are openly available on GitHub.

View on GitHub β†—