From 176fb6daf4aaa4e12d711a5a521489af0ee9f9a4 Mon Sep 17 00:00:00 2001 From: Chris Arderne Date: Thu, 20 Aug 2026 09:59:39 +0100 Subject: [PATCH] fix(webapp): call hooks directly and unconditionally (#4715) ## Summary Calls dashboard hooks directly instead of passing them as ordinary callback values, and subscribes to optional Ariakit stores through an unconditional hook. This keeps hook ordering stable while preserving the existing behavior when a provider is absent. --- apps/webapp/app/components/primitives/Select.tsx | 7 ++++--- apps/webapp/app/hooks/useChanged.ts | 3 +-- apps/webapp/app/hooks/useOrganizations.ts | 3 ++- apps/webapp/app/hooks/useProject.tsx | 3 ++- apps/webapp/app/hooks/useUser.ts | 3 ++- 5 files changed, 11 insertions(+), 8 deletions(-) diff --git a/apps/webapp/app/components/primitives/Select.tsx b/apps/webapp/app/components/primitives/Select.tsx index de453f3eb..70cc919a0 100644 --- a/apps/webapp/app/components/primitives/Select.tsx +++ b/apps/webapp/app/components/primitives/Select.tsx @@ -1,6 +1,7 @@ import * as Ariakit from "@ariakit/react"; import { type SelectProps as AriaSelectProps } from "@ariakit/react"; import { SelectValue } from "@ariakit/react-core/select/select-value"; +import { useStoreState } from "@ariakit/react-core/utils/store"; import { Link } from "@remix-run/react"; import * as React from "react"; import { Fragment, useMemo, useState } from "react"; @@ -484,7 +485,7 @@ export function SelectItem({ const render = combobox ? : props.render; const ref = React.useRef(null); const select = Ariakit.useSelectContext(); - const selectValue = select?.useState("value"); + const selectValue = useStoreState(select, "value"); const isChecked = React.useMemo(() => { if (!props.value || selectValue == null) return false; @@ -692,8 +693,8 @@ export function ComboBox({ ...props }: ComboBoxProps) { const combobox = Ariakit.useComboboxContext(); - const open = combobox?.useState("open"); - const input = combobox?.useState("baseElement"); + const open = useStoreState(combobox, "open"); + const input = useStoreState(combobox, "baseElement"); React.useEffect(() => { if (!open || !input) return; diff --git a/apps/webapp/app/hooks/useChanged.ts b/apps/webapp/app/hooks/useChanged.ts index e2f1b6215..430c1605a 100644 --- a/apps/webapp/app/hooks/useChanged.ts +++ b/apps/webapp/app/hooks/useChanged.ts @@ -2,7 +2,7 @@ import { useEffect, useRef } from "react"; /** Call a function when the id of the item changes */ export function useChanged( - getItem: () => T | undefined, + item: T | undefined, action: (item: T | undefined) => void, sendInitialUndefined = true ) { @@ -10,7 +10,6 @@ export function useChanged( const isInitialRender = useRef(true); const actionRef = useRef(action); const itemRef = useRef(); - const item = getItem(); const itemId = item?.id; actionRef.current = action; diff --git a/apps/webapp/app/hooks/useOrganizations.ts b/apps/webapp/app/hooks/useOrganizations.ts index 4070976da..4cd603b29 100644 --- a/apps/webapp/app/hooks/useOrganizations.ts +++ b/apps/webapp/app/hooks/useOrganizations.ts @@ -43,7 +43,8 @@ export function useOrganization(matches?: UIMatch[]) { } export const useOrganizationChanged = (action: (org: MatchedOrganization | undefined) => void) => { - useChanged(useOptionalOrganization, action); + const organization = useOptionalOrganization(); + useChanged(organization, action); }; export function useIsImpersonating(matches?: UIMatch[]) { diff --git a/apps/webapp/app/hooks/useProject.tsx b/apps/webapp/app/hooks/useProject.tsx index 2280694c1..2e04322c2 100644 --- a/apps/webapp/app/hooks/useProject.tsx +++ b/apps/webapp/app/hooks/useProject.tsx @@ -24,5 +24,6 @@ export function useProject(matches?: UIMatch[]) { } export const useProjectChanged = (action: (org: MatchedProject | undefined) => void) => { - useChanged(useOptionalProject, action); + const project = useOptionalProject(); + useChanged(project, action); }; diff --git a/apps/webapp/app/hooks/useUser.ts b/apps/webapp/app/hooks/useUser.ts index aa86ba638..2eed91b97 100644 --- a/apps/webapp/app/hooks/useUser.ts +++ b/apps/webapp/app/hooks/useUser.ts @@ -27,7 +27,8 @@ export function useUser(matches?: UIMatch[]): User { } export function useUserChanged(callback: (user: User | undefined) => void) { - useChanged(useOptionalUser, callback); + const user = useOptionalUser(); + useChanged(user, callback); } /**