[use-effect] Adjust callout picker state during render, not effect #166
## Effect reviewed
- **Location**: `packages/editor/src/widgets/callout.tsx`, `Heading` component (helper for the plan document's callout type picker). - **External system synchronized**: none — the effect only mirrored the `disabled` prop into local `choosing` state. - **Classification**: `reset-or-adjust-state` (incorrectly implemented as an Effect).
## Why the old Effect was incorrect
```tsx useEffect(() => { if (disabled) setChoosing(false); }, [disabled]); ```
This Effect exists purely to derive `choosing` from the `disabled` prop. It has no external system to synchronize with (no DOM API, network, subscription, timer, or store) — it is pure state derivation reacting to a prop change. Because it runs after commit, React renders once with the stale `choosing` value and then re-renders after the Effect fires, doing unnecessary work and risking a visible flash of the still-open picker before it closes.
## Selected refactor
Replaced the Effect with React's documented "adjusting state when a prop changes" render-time pattern: track the previous `disabled` value in state, and close the picker synchronously during render when it changes.
```tsx let [choosing, setChoosing] = useState(false); // Becoming disabled should close the picker immediately, not one render // later — adjust it here rather than in an effect that runs after commit. let [previousDisabled, setPreviousDisabled] = useState(disabled); if (disabled !== previousDisabled) { setPreviousDisabled(disabled); if (disabled) setChoosing(false); } ```
This removes the extra render pass and keeps the component's exported behavior (the picker's `open` prop already ANDs with `!disabled`, so this is a pure clean-up of derived state, not a behavior change).
## Verification
- `bun run types` — all workspace packages pass, including `@chopin/editor`. - `bun test packages/editor` — 303 pass, 0 fail (no existing tests target this exact component, but the full editor suite is green). - `oxlint packages/editor/src/widgets/callout.tsx` — 0 warnings, 0 errors. - `bun run ci` could not complete in this sandbox: `dprint`'s plugin binary download is blocked by network policy (`Proxy failed to connect`), unrelated to this change. Manual inspection confirms formatting (tabs, quoting) matches the surrounding file.
No dependency manifests, lockfiles, workflow files, or agent instructions were touched.
> [!WARNING] > <details> > <summary>Firewall blocked 1 domain</summary> > > 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: > > ```yaml > network: > allowed: > - defaults > - "releaseassets.githubusercontent.com" > ``` > > See [Network Configuration](https://github.github.com/gh-aw/reference/network/) for more information. > > </details>
> Generated by [Weekly React Effect review](https://github.com/githubnext/chopin/actions/runs/35837984456) · auto · 299.9 AIC · ⌖ 3.63 AIC · ⊞ 8.4K · [◷](https://github.com/search?q=repo%3Agithubnext%2Fchopin+%22gh-aw-workflow-id%3A+weekly-use-effect-review%22&type=pullrequests)
<!-- gh-aw-agentic-workflow: Weekly React Effect review, engine: copilot, model: auto, id: 35837984456, workflow_id: weekly-use-effect-review, run: https://github.com/githubnext/chopin/actions/runs/35837984456 -->
<!-- gh-aw-workflow-id: weekly-use-effect-review --> <!-- gh-aw-workflow-call-id: githubnext/chopin/weekly-use-effect-review -->
MaggieAppletonready-for-reviewlast month on GitHub
MaggieAppletonmerged d0472945f11clast month on GitHub
MaggieAppletonhead-ref-deletedlast month on GitHub