From 5dad1721cdb75efa2f537adee15c3168b408ecfd Mon Sep 17 00:00:00 2001 From: Neil <4138956+nwparker@users.noreply.github.com> Date: Sat, 30 May 2026 00:35:32 -0700 Subject: [PATCH] fix: guard installed skill discovery updates (#3528) --- .../src/hooks/useInstalledAgentSkills.ts | 30 ++++++++++++++++--- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/src/renderer/src/hooks/useInstalledAgentSkills.ts b/src/renderer/src/hooks/useInstalledAgentSkills.ts index 1b5bbf8294a..01b4e7f3b20 100644 --- a/src/renderer/src/hooks/useInstalledAgentSkills.ts +++ b/src/renderer/src/hooks/useInstalledAgentSkills.ts @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useMemo, useState } from 'react' +import { useCallback, useEffect, useMemo, useRef, useState } from 'react' import type { DiscoveredSkill, SkillDiscoveryResult, SkillSourceKind } from '../../../shared/skills' const INSTALLED_AGENT_SKILLS_CHANGED_EVENT = 'orca:installed-agent-skills-changed' @@ -118,24 +118,46 @@ export function useInstalledAgentSkill( const [result, setResult] = useState(cachedDiscovery) const [loading, setLoading] = useState(enabled && !cachedDiscovery) const [error, setError] = useState(null) + // Why: skill scans can outlive transient settings/onboarding panels; keep + // the module cache update but skip React state writes after unmount. + const mountedRef = useRef(true) + + useEffect(() => { + mountedRef.current = true + return () => { + mountedRef.current = false + } + }, []) const refresh = useCallback( async (force = true): Promise => { if (!enabled) { - setLoading(false) + if (mountedRef.current) { + setLoading(false) + } return } - setLoading(true) + if (mountedRef.current) { + setLoading(true) + } try { const next = await discoverInstalledAgentSkills(force) + if (!mountedRef.current) { + return + } setResult(next) setError(null) } catch (refreshError) { + if (!mountedRef.current) { + return + } setError( refreshError instanceof Error ? refreshError.message : 'Could not scan installed skills.' ) } finally { - setLoading(false) + if (mountedRef.current) { + setLoading(false) + } } }, [enabled]