fix(ui): invalidate org queries after team mutations#25812
Conversation
Team create/delete/update can change which teams belong to an organization (via teamCreateCall, teamDeleteCall, and teamUpdateCall when organization_id changes). Without invalidating the React Query cache for organizations, the org info page's teams list and any useOrganizations() consumer (e.g. the team edit form's organization dropdown) stay stale until a hard reload. Export organizationKeys from useOrganizations and invalidate organizationKeys.all after each successful team mutation, matching the pattern used in hooks/projects, hooks/budgets, and hooks/accessGroups.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Greptile SummaryTwo coordinated changes fix stale org data after team mutations: Confidence Score: 5/5Safe to merge — changes are narrowly scoped cache invalidations and a clean hook migration with no logic changes. All six files have straightforward, well-tested changes. No new logic is introduced: mutations now call invalidateQueries using an exported key factory, and organization_view migrates to an already-existing hook. Tests are correctly updated to mock the hook rather than the raw network call, and renderWithProviders supplies the required QueryClient context. No P0 or P1 findings. No files require special attention.
|
| Filename | Overview |
|---|---|
| ui/litellm-dashboard/src/app/(dashboard)/hooks/organizations/useOrganizations.ts | Adds export to organizationKeys so downstream consumers can reference the same key factory; no functional change to the hook logic. |
| ui/litellm-dashboard/src/components/organization/organization_view.tsx | Replaces manual fetch/useEffect with useOrganization hook; each post-mutation fetchOrgInfo call becomes queryClient.invalidateQueries. Clean reduction in code with no behavioral regression. |
| ui/litellm-dashboard/src/components/organization/organization_view.test.tsx | Tests correctly updated to mock useOrganization instead of organizationInfoCall; switches to renderWithProviders for proper QueryClient context; no coverage regression. |
| ui/litellm-dashboard/src/app/(dashboard)/teams/TeamsView.tsx | Adds org cache invalidation after teamDeleteCall; straightforward and consistent with the established pattern. |
| ui/litellm-dashboard/src/app/(dashboard)/teams/components/modals/CreateTeamModal.tsx | Adds org cache invalidation after teamCreateCall; straightforward. |
| ui/litellm-dashboard/src/components/team/TeamInfo.tsx | Adds org cache invalidation after teamUpdateCall; consistent with the pattern added in the other team files. |
Sequence Diagram
sequenceDiagram
participant User
participant Component as TeamsView / CreateTeamModal / TeamInfo / OrgView
participant API
participant QC as QueryClient
participant useOrg as useOrganization(id)
User->>Component: Mutate (create/update/delete team or org member)
Component->>API: teamCreateCall / teamDeleteCall / teamUpdateCall / org member call
API-->>Component: Success response
Component->>QC: invalidateQueries(organizationKeys.all)
QC->>useOrg: Mark detail query stale → refetch
QC->>QC: Mark list query stale → refetch
useOrg->>API: GET /organization/{id}
API-->>useOrg: Fresh org data
useOrg-->>Component: Re-render org info page with updated teams/members
Reviews (4): Last reviewed commit: "Merge remote-tracking branch 'origin/lit..." | Re-trigger Greptile
Replace the local orgData/loading useState + fetchOrgInfo useEffect in
OrganizationInfoView with the existing useOrganization(id) React Query
hook, and replace each post-mutation fetchOrgInfo() call with
queryClient.invalidateQueries({ queryKey: organizationKeys.all }).
This makes the org info page benefit from the React Query cache
invalidation already added for team mutations: editing a team's
organization elsewhere now refreshes the org's Teams badge list (and
all other org-derived data) without a hard reload.
Replace the organizationInfoCall mock with a vi.mock of the useOrganizations hook module that stubs useOrganization (and organizationKeys, which the component still imports for invalidation). Each test now sets mockUseOrganization.mockReturnValue(...) instead of mocking the underlying network call, matching the existing pattern in TeamInfo.test.tsx. Renders go through the canonical renderWithProviders helper from tests/test-utils so the component's useQueryClient() call has a QueryClientProvider in context. This is the standard wrapper used by ~96 other test files in the dashboard. Fixes "No QueryClient set" failures in the 4 organization_view tests introduced by the imperative-fetch -> useOrganization migration.
…itellm_fix-invalidate-orgs-on-team-mutation
ed0138b
into
litellm_internal_staging
Summary
The organization info page didn't reflect team↔org membership changes until a hard reload. Two coordinated fixes:
teamCreateCall,teamDeleteCall,teamUpdateCall) inTeamsView,CreateTeamModal, andTeamInfo. Pattern matcheshooks/projects/hooks/budgets/hooks/accessGroups—organizationKeys.allso list and detail queries both invalidate. Requires exportingorganizationKeysfromuseOrganizations.ts.organization_view.tsxto the existinguseOrganization(id)hook, dropping localorgData/loadingstate, thefetchOrgInfofunction, and itsuseEffect. Each of the 4 post-mutationfetchOrgInfo()calls becomesqueryClient.invalidateQueries({ queryKey: organizationKeys.all }). Without this migration, step 1 had no visible effect on the org info page since it was reading from a separate manually-managed copy of the data. Net: −26 / +9 lines.Out of scope (follow-up): the Teams page Organization column staleness —
useFetchTeamsdoesn't use React Query at all, which is a larger refactor.Screenshots
Before
Edit a team's organization elsewhere → return to old org's info page → moved team still appears in the Teams badge list until
Cmd+R.After
Same flow → moved team disappears from the source org and appears in the destination org without a reload.
Test plan
Pre-req: 2 organizations and 1 team assigned to one of them.
Cmd+Rneeded.