Skip to content

Handling Events

React handles events with JSX attributes that take functions as values. The syntax is close to HTML’s onclick but with important differences.

Pass a function reference to a camelCase event prop:

function DeleteButton({ onDelete }) {
return (
<button onClick={onDelete}>Delete</button>
);
}

Pass the function reference — not a call. onClick={onDelete} is correct. onClick={onDelete()} calls the function immediately when the component renders, which is almost never what you want.

For short logic, an inline arrow function is fine:

<button onClick={() => setCount(count + 1)}>+</button>

The arrow function is a new function on every render, but for simple handlers this does not matter. If performance becomes a concern (in a large list), useCallback (covered in Module 05) prevents recreating the function unnecessarily.

React passes a SyntheticEvent to every handler. It has the same shape as a native DOM event but works consistently across browsers:

function handleChange(e) {
console.log(e.target.value); // the input's current value
}
<input onChange={handleChange} />

For form submissions, call e.preventDefault() to stop the browser from reloading the page:

function handleSubmit(e) {
e.preventDefault();
// process the form
}
<form onSubmit={handleSubmit}>
EventWhere it is used
onClickDelete buttons, nav arrows, toggle buttons
onChangeAll text and number inputs
onSubmitIncome add form, transaction add form
onKeyDownInline edit fields (save on Enter)

The inline edit in CategoryCard uses onKeyDown to save when the user presses Enter:

<input
value={nameVal}
onChange={e => setNameVal(e.target.value)}
onKeyDown={e => { if (e.key === 'Enter') saveName(); }}
autoFocus
/>

When rendering a list, you often need to pass the item’s ID to a handler. Use an arrow function to close over the value:

{incomeSources.map(src => (
<li key={src.id}>
{src.name}
<button onClick={() => onDelete(src.id)}>×</button>
</li>
))}

The () => onDelete(src.id) arrow captures the current src.id for each item in the list.

  1. In IncomeSection, add a delete button next to each income row that logs the item’s id to the console when clicked.
  2. Add a form submit handler that calls e.preventDefault(), logs the current name and amount state, then clears both fields.
  3. Add an onKeyDown handler to the name input that clears the field when Escape is pressed (e.key === 'Escape').
  4. Confirm all three handlers work as expected in the browser.
  • Attach handlers with camelCase event props: onClick, onChange, onSubmit, onKeyDown.
  • Pass the function reference, not a call — onClick={fn} not onClick={fn()}.
  • The SyntheticEvent object has e.target.value, e.key, e.preventDefault(), and all the usual DOM event properties.
  • Use arrow functions in map to close over each item’s identity when passing IDs to handlers.