React Forum
Blog & Guide Responses
Nov 05, 2022 · 04:00 AM

React useEffect - discussion (2022-11-05)

Started by Theo Bennett
externalreact.devuseEffecteffectscleanupsync

We keep re-litigating what effects are “for” and the disagreements usually come down to: are we using effects to synchronize with external systems, or are we patching state after render because we didn’t define the contract clearly enough?

Read the docs

What effect patterns do you still allow in 2022 (subscriptions, analytics, DOM) and which ones do you aggressively delete? Do you have conventions that make effect behavior visible from the UI (status markers, last-run evidence) instead of hiding it in logs? How do you migrate an effect-driven sync into a route contract key / derived evidence story?

Comments (10)

Back to latest
Maya Henson
Nov 05, 2022 · 04:06 AM

If it’s internal state sync, delete it. If it’s external system sync, keep it but make it boring and visible.

Dmitri Kline
Nov 05, 2022 · 04:14 AM

The rule that helped us: effects must either (a) integrate with the outside world or (b) write evidence the UI can render.

If it does neither, it’s just secret work.

Related: Testing and Debugging and Using Effects to Keep State Consistent.

Salma Qureshi
Nov 05, 2022 · 04:22 AM

We added a visible effect marker so timing bugs stopped being ghosts:

tsx
function useEffectMarker(name: string, deps: unknown[]) {
  const [status, setStatus] = useState<'start' | 'active' | 'cleanup'>('start');
  useEffect(() => {
    setStatus('start');
    setStatus('active');
    return () => setStatus('cleanup');
  }, deps);
  return { name, status } as const;
}

const e = useEffectMarker('presence:socket', [roomId]);
return <div data-effect={e.name} data-status={e.status} />;
Keira Santos
Nov 05, 2022 · 04:31 AM

Counterpoint: markers can normalize bad designs.

I’d rather see teams delete the effect and store derived evidence than become “good” at writing effects.

Theo Bennett
Nov 05, 2022 · 04:36 AM

I agree in principle. The markers are for the effects we can’t delete (subscriptions, analytics).

For internal sync effects, the marker is a temporary tool to prove what’s happening until we migrate to contract keys.

Keira Santos
Nov 05, 2022 · 04:39 AM

That’s a good distinction: unavoidable sync vs “we didn’t decide the contract”.

Camille Duarte
Nov 05, 2022 · 04:47 AM

The effects that hurt us most were URL sync effects.

Once we treated URL as hint and route state as truth, the effect disappeared and so did the weird back button behavior.

Rowan Pierce
Nov 05, 2022 · 04:56 AM

We migrated a “fix state after render” effect by writing the derived value once in the route doc:

tsx
const doc = useRouteDoc('inbox');
const derived = useMemo(() => derive(state), [state]);
doc.write('derivedEvidence', derived);
return <div data-derived="stored" />;
Amina Farouk
Nov 05, 2022 · 05:07 AM

Strict Mode double-invoking effects is a great audit for “is this effect actually safe”.

Anything that breaks was relying on timing, not contracts.

Link: Strict Mode.

Priya Liao
Nov 05, 2022 · 05:21 AM

Cleanup discipline is the difference between “we have one subscription” and “we have 9 subscriptions and nobody knows why”.

Inez Park
Nov 05, 2022 · 05:32 AM

If your effect changes behavior and nothing in the UI can prove it happened, you’ll debug it by reading code every time.

Benji Rios
Nov 05, 2022 · 05:44 AM

Effects aren’t evil. Invisible effects are.

Make them boring, scoped, and visible — or delete them and move the decision into the route contract.