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?
Removing Effect DependenciesRead docs ↗

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

Create account

Network0 requests

    No requests yet.

    Clicks
    0
    Renders
    0
    Effect runs
    0
    POSTs
    0
    useEffect(…, [submitted, theme])
    In the handlerGood

    Create account

    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

      Ship the handler, not the flag.

      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.