Handling Events and Forms
Event handlers
function StartButton() {n function handleClick() {n console.log("Starting course...");n }nn return <button onClick={handleClick}>Start Course</button>;n}
React event handlers use camelCase (onClick, not onclick) and are passed an actual function reference, not a string — onClick={handleClick}, never onClick={handleClick()}, which would call the function immediately during render rather than waiting for the actual click.
Controlled form inputs
function ContactForm() {n const [name, setName] = useState("");nn function handleSubmit(e) {n e.preventDefault(); // stop the browser's default full-page reloadn console.log("Submitting:", name);n }nn return (n <form onSubmit={handleSubmit}>n <inputn value={name}n onChange={(e) => setName(e.target.value)}n />n <button type="submit">Send</button>n </form>n );n}
A “controlled” input has its value driven entirely by React state — every keystroke calls setName, and the input’s displayed value always reflects the current state. This gives you a single source of truth for form data and makes validation straightforward, though it does mean React re-renders on every keystroke.
e.preventDefault()
Without e.preventDefault(), submitting the form does what a plain HTML form always does — a full page reload — which would immediately wipe out your component’s state and any progress toward a single-page application feel. This exact call is present in nearly every real React form.
Passing data back up: callback props
function SearchBox({ onSearch }) {n return <input onChange={(e) => onSearch(e.target.value)} />;n}nnfunction App() {n const [query, setQuery] = useState("");n return <SearchBox onSearch={setQuery} />;n}
Since props only flow one direction (parent to child), a child component that needs to notify its parent of something calls a function the parent passed it as a prop — this is the standard React pattern for “lifting state up” to a shared parent.