Use useDeferredValue for search dropdown rendering

Defer rendering of bestiary suggestions and player character matches
in ActionBar so the input stays responsive as the bestiary grows.
Keyboard navigation and selection logic still use the latest values.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Lukas
2026-03-14 12:35:38 +01:00
parent 01f2bb3ff1
commit 179c3658ad

View File

@@ -9,7 +9,12 @@ import {
Plus,
Users,
} from "lucide-react";
import { type FormEvent, type RefObject, useState } from "react";
import {
type FormEvent,
type RefObject,
useDeferredValue,
useState,
} from "react";
import type { SearchResult } from "../hooks/use-bestiary.js";
import { cn } from "../lib/utils.js";
import { D20Icon } from "./d20-icon.js";
@@ -270,6 +275,8 @@ export function ActionBar({
const [nameInput, setNameInput] = useState("");
const [suggestions, setSuggestions] = useState<SearchResult[]>([]);
const [pcMatches, setPcMatches] = useState<PlayerCharacter[]>([]);
const deferredSuggestions = useDeferredValue(suggestions);
const deferredPcMatches = useDeferredValue(pcMatches);
const [suggestionIndex, setSuggestionIndex] = useState(-1);
const [queued, setQueued] = useState<QueuedCreature | null>(null);
const [customInit, setCustomInit] = useState("");
@@ -394,7 +401,8 @@ export function ActionBar({
}
};
const hasSuggestions = suggestions.length > 0 || pcMatches.length > 0;
const hasSuggestions =
deferredSuggestions.length > 0 || deferredPcMatches.length > 0;
const handleKeyDown = (e: React.KeyboardEvent) => {
if (!hasSuggestions) return;
@@ -495,10 +503,10 @@ export function ActionBar({
)}
</button>
)}
{browseMode && suggestions.length > 0 && (
{browseMode && deferredSuggestions.length > 0 && (
<div className="absolute bottom-full z-50 mb-1 w-full rounded-md border border-border bg-card shadow-lg">
<ul className="max-h-48 overflow-y-auto py-1">
{suggestions.map((result, i) => (
{deferredSuggestions.map((result, i) => (
<li key={creatureKey(result)}>
<button
type="button"
@@ -524,8 +532,8 @@ export function ActionBar({
{!browseMode && hasSuggestions && (
<AddModeSuggestions
nameInput={nameInput}
suggestions={suggestions}
pcMatches={pcMatches}
suggestions={deferredSuggestions}
pcMatches={deferredPcMatches}
suggestionIndex={suggestionIndex}
queued={queued}
onDismiss={dismissSuggestions}