Skip to content

[use-effect] Derive effective access during render instead of an Effect - #155

Draft
github-actions[bot] wants to merge 1 commit into
mainfrom
automation/use-effect/room-workspace-effective-access-a57d40866c71bed0
Draft

github-actions[bot] wants to merge 1 commit into
mainfrom
automation/use-effect/room-workspace-effective-access-a57d40866c71bed0

Conversation

@github-actions

Copy link
Copy Markdown
Contributor

Effect reviewed

RoomWorkspace (apps/web/src/room-workspace.tsx, previously lines 332-338):

useEffect(() => {
	let editable = canEdit && !archivedAt;
	latestCanEdit.current = editable;
	latestCanManage.current = canManage;
	setEffectiveCanEdit(editable);
	setEffectiveCanManage(canManage);
}, [archivedAt, canEdit, canManage, room]);

Classification

derive-render.

Why the Effect was incorrect

effectiveCanEdit/effectiveCanManage start out equal to a pure function of the canEdit/archivedAt/canManage props (useState(canEdit && !archivedAt) / useState(canManage)). This Effect only re-ran that same pure computation whenever those props changed — it never talked to any external system (no subscription, no DOM, no network). Because it ran in an Effect instead of during render, a prop change was visible for one extra paint with the old authorization values before the Effect fired and corrected them. That is exactly the case the React docs call out: you don't need an Effect for adjusting state that is a pure function of props.

The room dependency was already vestigial — RoomWorkspace is always mounted with key={channel.id} from its callers (document-workspace-host.tsx), so room never changes without remounting the whole component and resetting all state; it did not need to participate in the comparison.

Fix

Replaced the Effect with the React "adjust state during render when a prop changes" pattern: track the previous { archivedAt, canEdit, canManage } in a ref, and if any of them differ from the current render's props, update the ref and call the state setters synchronously in the render body (before any JSX is produced). This keeps the exact same values and the same latestCanEdit/latestCanManage ref side effects that later session:* socket handlers rely on (those still update the same refs/state directly, unaffected by this change), but removes the extra render pass.

Verification

  • bun run types — all workspaces (@chopin/web included) type-check cleanly.
  • bun test apps/web — 304 pass, 0 fail (no regressions).
  • bunx oxlint apps/web/src/room-workspace.tsx — 0 warnings, 0 errors.
  • bun run ci could not complete in this sandbox: dprint check fails to download its TypeScript plugin binary because outbound network access to GitHub Releases is blocked here. oxlint (run standalone above) and the token checker were not otherwise affected by this change.

Only this one Effect/file was touched, per the one-violation-per-PR constraint.

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • releaseassets.githubusercontent.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "releaseassets.githubusercontent.com"

See Network Configuration for more information.

Generated by Weekly React Effect review · auto · 149.2 AIC · ⌖ 4.45 AIC · ⊞ 7.5K ·

The effectiveCanEdit/effectiveCanManage Effect in RoomWorkspace only
recomputed a pure function of the canEdit/archivedAt/canManage props; it
did not synchronize with any external system, so it caused an extra
render showing stale authorization before the Effect ran. Replace it
with the React 'adjust state during render when a prop changes'
pattern, comparing the previous props in a ref and updating state
synchronously in the render body. The latestCanEdit/latestCanManage
refs (read by later socket handlers) and the state setters keep their
prior update semantics.

Verified with 'bun run types' (all workspaces pass) and 'bun test
apps/web' (304 pass, 0 fail); 'bunx oxlint apps/web/src/room-workspace.tsx'
reports 0 warnings/errors. 'bun run ci' could not run locally because the
dprint plugin download is blocked in this sandbox.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants