Skip to content

Commit cee08d2

Browse files
perf(web): the draft hero headline compiles without manual memoization
Co-Authored-By: Claude Opus 5.5 <[email protected]>
1 parent 70d60e0 commit cee08d2

2 files changed

Lines changed: 47 additions & 81 deletions

File tree

‎apps/web/reactCompiledFiles.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,4 +96,5 @@ export const REACT_COMPILED_FILES = [
9696
"apps/web/src/components/pullRequest/PullRequestDetailPanel.tsx",
9797
"apps/web/src/components/ThreadTerminalDrawer.tsx",
9898
"apps/web/src/components/settings/SettingsPanels.tsx",
99+
"apps/web/src/components/chat/DraftHeroHeadline.tsx",
99100
] as const;

‎apps/web/src/components/chat/DraftHeroHeadline.tsx‎

Lines changed: 46 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { scopedProjectKey, scopeProjectRef } from "@t3tools/client-runtime/envir
55
import { isScratchProject } from "@t3tools/client-runtime/state/projects";
66
import { FolderPlusIcon } from "lucide-react";
77
import { useAtomValue } from "@effect/atom-react";
8-
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
8+
import { useEffect, useRef, useState } from "react";
99

1010
import { openCommandPalette } from "~/commandPaletteBus";
1111
import { shortcutLabelForCommand } from "~/keybindings";
@@ -72,68 +72,43 @@ export function DraftHeroHeadline({
7272
const getComposerDraft = useComposerDraftStore((store) => store.getComposerDraft);
7373
const applyStickyState = useComposerDraftStore((store) => store.applyStickyState);
7474
const setModelSelection = useComposerDraftStore((store) => store.setModelSelection);
75-
const openAddProject = useCallback(() => openCommandPalette({ open: "add-project" }), []);
75+
const openAddProject = () => openCommandPalette({ open: "add-project" });
7676
const { scratchEnvironmentId, scratchWorkspaceRootFor, openScratchProject } = useScratchProject();
7777
const openProjectDraft = useNewThreadHandler();
7878
const keybindings = useAtomValue(primaryServerKeybindingsAtom);
79+
const [pickerOpen, setPickerOpen] = useState(false);
80+
const [pickerQuery, setPickerQuery] = useState("");
81+
const pickerFilter = useComboboxFilter();
7982

80-
const environmentLabelById = useMemo(
81-
() =>
82-
new Map(
83-
environments.map((environment) => [environment.environmentId, environment.label] as const),
84-
),
85-
[environments],
83+
const environmentLabelById = new Map(
84+
environments.map((environment) => [environment.environmentId, environment.label] as const),
8685
);
87-
const projectGroups = useMemo(
88-
() =>
89-
sortLogicalProjectsForSidebar(
90-
buildSidebarProjectSnapshots({
91-
projects,
92-
settings: projectGroupingSettings,
93-
primaryEnvironmentId,
94-
resolveEnvironmentLabel: (environmentId) =>
95-
environmentLabelById.get(environmentId) ?? null,
96-
}),
97-
threads,
98-
projectSortOrder,
99-
),
100-
[
101-
environmentLabelById,
102-
primaryEnvironmentId,
103-
projectGroupingSettings,
104-
projectSortOrder,
86+
const projectGroups = sortLogicalProjectsForSidebar(
87+
buildSidebarProjectSnapshots({
10588
projects,
106-
threads,
107-
],
108-
);
109-
const showProjectEnvironments = useMemo(
110-
() => projectGroupsSpanEnvironments(projectGroups),
111-
[projectGroups],
112-
);
113-
const environmentMachineById = useMemo(
114-
() =>
115-
new Map(
116-
environments.map(
117-
(environment) =>
118-
[
119-
environment.environmentId,
120-
resolveEnvironmentMachineKind(environment.serverConfig),
121-
] as const,
122-
),
123-
),
124-
[environments],
89+
settings: projectGroupingSettings,
90+
primaryEnvironmentId,
91+
resolveEnvironmentLabel: (environmentId) => environmentLabelById.get(environmentId) ?? null,
92+
}),
93+
threads,
94+
projectSortOrder,
12595
);
126-
const projectPickerEntries = useMemo(
127-
() =>
128-
buildSidebarProjectPickerEntries({
129-
groups: projectGroups,
130-
preferredProjectRef: activeProjectRef,
131-
}),
132-
[activeProjectRef, projectGroups],
96+
const showProjectEnvironments = projectGroupsSpanEnvironments(projectGroups);
97+
const environmentMachineById = new Map(
98+
environments.map(
99+
(environment) =>
100+
[
101+
environment.environmentId,
102+
resolveEnvironmentMachineKind(environment.serverConfig),
103+
] as const,
104+
),
133105
);
134-
const projectEntryByKey = useMemo(
135-
() => new Map(projectPickerEntries.map((entry) => [entry.group.projectKey, entry] as const)),
136-
[projectPickerEntries],
106+
const projectPickerEntries = buildSidebarProjectPickerEntries({
107+
groups: projectGroups,
108+
preferredProjectRef: activeProjectRef,
109+
});
110+
const projectEntryByKey = new Map(
111+
projectPickerEntries.map((entry) => [entry.group.projectKey, entry] as const),
137112
);
138113
const activeProjectGroup =
139114
activeProjectRef === null
@@ -148,13 +123,9 @@ export function DraftHeroHeadline({
148123
const hasResolvedProject = activeProjectTitle !== null;
149124
const canChooseProject = projectPickerEntries.length > 0;
150125
const shouldShowProjectMenu = canChooseProject;
151-
const menuEntries = useMemo(
152-
() =>
153-
projectPickerEntries.filter(
154-
({ targetProject }) =>
155-
!isScratchProject(targetProject, scratchWorkspaceRootFor(targetProject.environmentId)),
156-
),
157-
[projectPickerEntries, scratchWorkspaceRootFor],
126+
const menuEntries = projectPickerEntries.filter(
127+
({ targetProject }) =>
128+
!isScratchProject(targetProject, scratchWorkspaceRootFor(targetProject.environmentId)),
158129
);
159130
const activeProject =
160131
activeProjectRef === null
@@ -171,25 +142,19 @@ export function DraftHeroHeadline({
171142
const isScratchDraft =
172143
activeProject !== null && isScratchProject(activeProject, scratchWorkspaceRoot);
173144

174-
const pickerItems = useMemo<readonly PickerItem[]>(
175-
() => [
176-
...menuEntries.map(({ group }) => ({ value: group.projectKey, label: group.displayName })),
177-
{ value: ADD_PROJECT_VALUE, label: "Add project" },
178-
],
179-
[menuEntries],
180-
);
181-
const [pickerOpen, setPickerOpen] = useState(false);
182-
const [pickerQuery, setPickerQuery] = useState("");
183-
const pickerFilter = useComboboxFilter();
184-
const filteredPickerItems = useMemo(() => {
185-
const query = pickerQuery.trim();
186-
if (query.length === 0) return pickerItems;
187-
return pickerItems.filter(
188-
(item) =>
189-
item.value !== ADD_PROJECT_VALUE &&
190-
pickerFilter.contains(item, query, (candidate) => candidate.label),
191-
);
192-
}, [pickerFilter, pickerItems, pickerQuery]);
145+
const pickerItems: readonly PickerItem[] = [
146+
...menuEntries.map(({ group }) => ({ value: group.projectKey, label: group.displayName })),
147+
{ value: ADD_PROJECT_VALUE, label: "Add project" },
148+
];
149+
const pickerSearch = pickerQuery.trim();
150+
const filteredPickerItems =
151+
pickerSearch.length === 0
152+
? pickerItems
153+
: pickerItems.filter(
154+
(item) =>
155+
item.value !== ADD_PROJECT_VALUE &&
156+
pickerFilter.contains(item, pickerSearch, (candidate) => candidate.label),
157+
);
193158
const selectedPickerItem = pickerItems.find((item) => item.value === activeProjectKey) ?? null;
194159

195160
// The picker can change the draft's target while the no-project home is

0 commit comments

Comments
 (0)