[Bug] GeneralSection handleNotificationToggle fires IPC call inside setState updater
#400 aperta il 15 apr 2026
Metriche repository
- Star
- (519 star)
- Metriche merge PR
- (Metriche PR in attesa)
Descrizione
Problem
GeneralSection.handleNotificationToggle performs an IPC side-effect inside a setState updater. React explicitly disallows this — state updaters must be pure functions. In React Strict Mode (enabled in dev), updaters are invoked twice to detect impurity, which means window.clawwork.updateSettings(...) fires twice for every notification toggle, persisting the same change twice and doubling the IPC round-trip cost.
Location
File: packages/desktop/src/renderer/layouts/Settings/sections/GeneralSection.tsx:102-111
const handleNotificationToggle = useCallback(
(key: 'taskComplete' | 'approvalRequest' | 'gatewayDisconnect', value: boolean) => {
setNotifyState((prev) => {
const next = { ...prev, [key]: value };
window.clawwork.updateSettings({ notifications: next }); // ← side effect in updater
return next;
});
},
[],
);
Fix Approach
Compute the new state outside the updater, then dispatch both the state update and the IPC call as separate effects:
const handleNotificationToggle = useCallback(
(key: 'taskComplete' | 'approvalRequest' | 'gatewayDisconnect', value: boolean) => {
const next = { ...notifyState, [key]: value };
setNotifyState(next);
window.clawwork.updateSettings({ notifications: next });
},
[notifyState],
);
Or, if you want to avoid re-creating the callback on every state change, keep a ref that tracks the latest notifyState and use it inside the callback.
Verification
- Run
pnpm check— must pass. - Manual: in dev mode (Strict Mode enabled), toggle a notification switch and confirm only a single IPC call fires in the main-process logs.
Context
- WG: UI & Design System
- Priority: Low (good first issue)
- Estimated effort: 10-15 minutes