Ship the handler, not the flag.
Side effects go in handlers
Run a click's side effect in its handler, not in an effect on a flag.
react.devReact docs
Reference: Should this code move to an event handler?
From vercel-react-best-practices, rule rerender-move-effect-to-event.
One submit, how many requests?
Register in each form, then flip the theme.
Flag + effectBad
Network0 requests
No requests yet.
- Clicks
- 0
- Renders
- 0
- Effect runs
- 0
- POSTs
- 0
useEffect(…, [submitted, theme])In the handlerGood
Network0 requests
No requests yet.
- Clicks
- 0
- Renders
- 0
- Handler calls
- 0
- POSTs
- 0
onSubmit={handleSubmit}function handleSubmit(e) {
e.preventDefault()
post('/api/register', { email })
showToast('Registered', theme)
}
Effects rerun on any dep
Like, then change language and text size.
Where
track firesLive- Renders
- 1
- Likes you gave
- 0
- Effect: runs / tracks
- 1 / 0
- Handler: calls / tracks
- 0 / 0
function handleLike() {
setLiked(!liked)
if (!liked) track('like', { postId, locale })
}
Why it matters, pros and cons
Why it matters
An effect can't tell a click from a locale change. Any dependency replays it.
Pros
- One action, one side effect.
- No flag to reset; repeat submits work.
- No dependency array for the linter.
Cons
- Work caused by being displayed belongs in an effect.
- Need the latest value without re-running? Use
useEffectEvent. - Shared work: extract a function, call it from each handler.