Skip to content

Commit 9631b66

Browse files
committed
fix: maintain active index on async registered actions
1 parent 8250599 commit 9631b66

File tree

1 file changed

+38
-10
lines changed

1 file changed

+38
-10
lines changed

src/KBarResults.tsx

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ export const KBarResults: React.FC<KBarResultsProps> = (props) => {
4545
if (event.isComposing) {
4646
return;
4747
}
48-
4948
if (event.key === "ArrowUp" || (event.ctrlKey && event.key === "p")) {
5049
event.preventDefault();
5150
event.stopPropagation();
@@ -84,8 +83,9 @@ export const KBarResults: React.FC<KBarResultsProps> = (props) => {
8483
activeRef.current?.click();
8584
}
8685
};
87-
window.addEventListener("keydown", handler, {capture: true});
88-
return () => window.removeEventListener("keydown", handler, {capture: true});
86+
window.addEventListener("keydown", handler, { capture: true });
87+
return () =>
88+
window.removeEventListener("keydown", handler, { capture: true });
8989
}, [query]);
9090

9191
// destructuring here to prevent linter warning to pass
@@ -100,19 +100,47 @@ export const KBarResults: React.FC<KBarResultsProps> = (props) => {
100100
});
101101
}, [activeIndex, scrollToIndex]);
102102

103+
// reset active index only when search or root action changes
103104
React.useEffect(() => {
104-
// TODO(tim): fix scenario where async actions load in
105-
// and active index is reset to the first item. i.e. when
106-
// users register actions and bust the `useRegisterActions`
107-
// cache, we won't want to reset their active index as they
108-
// are navigating the list.
109105
query.setActiveIndex(
110106
// avoid setting active index on a group
111-
typeof props.items[START_INDEX] === "string"
107+
typeof itemsRef.current[START_INDEX] === "string"
112108
? START_INDEX + 1
113109
: START_INDEX
114110
);
115-
}, [search, currentRootActionId, props.items, query]);
111+
}, [search, currentRootActionId, query]);
112+
113+
// adjust active index when items change (ie when actions load async)
114+
React.useEffect(() => {
115+
const currentIndex = activeIndex;
116+
const maxIndex = itemsRef.current.length - 1;
117+
118+
if (currentIndex > maxIndex && maxIndex >= 0) {
119+
let newIndex = maxIndex;
120+
if (typeof itemsRef.current[newIndex] === "string" && newIndex > 0) {
121+
newIndex -= 1;
122+
}
123+
query.setActiveIndex(newIndex);
124+
} else if (
125+
currentIndex <= maxIndex &&
126+
typeof itemsRef.current[currentIndex] === "string"
127+
) {
128+
let newIndex = currentIndex + 1;
129+
if (
130+
newIndex > maxIndex ||
131+
typeof itemsRef.current[newIndex] === "string"
132+
) {
133+
newIndex = currentIndex - 1;
134+
}
135+
if (
136+
newIndex >= 0 &&
137+
newIndex <= maxIndex &&
138+
typeof itemsRef.current[newIndex] !== "string"
139+
) {
140+
query.setActiveIndex(newIndex);
141+
}
142+
}
143+
}, [props.items, activeIndex, query]);
116144

117145
const execute = React.useCallback(
118146
(item: RenderParams["item"]) => {

0 commit comments

Comments
 (0)