mirror of
https://github.com/BerriAI/litellm.git
synced 2026-08-28 05:25:59 +00:00
refactor(ui): migrate straightforward value debounces to react-pacer (#33042)
* refactor(ui): standardize debounce waits behind shared DEBOUNCE_WAIT_MS constant * build(ui): bump @tanstack/react-pacer from 0.2.0 to 0.22.1 * refactor(ui): migrate straightforward value debounces to react-pacer
This commit is contained in:
parent
da5ed97ff2
commit
20d021eb6a
4 changed files with 23 additions and 38 deletions
|
|
@ -1,6 +1,8 @@
|
|||
"use client";
|
||||
|
||||
import React, { useState, useEffect, useCallback } from "react";
|
||||
import { useDebouncedValue } from "@tanstack/react-pacer/debouncer";
|
||||
import { DEBOUNCE_WAIT_MS } from "@/utils/debounceConstants";
|
||||
import {
|
||||
SearchIcon,
|
||||
PlusIcon,
|
||||
|
|
@ -728,6 +730,7 @@ export function TeamGuardrailsTab({ accessToken }: TeamGuardrailsTabProps) {
|
|||
rejected: 0,
|
||||
});
|
||||
const [search, setSearch] = useState("");
|
||||
const [searchDebounced] = useDebouncedValue(search, { wait: DEBOUNCE_WAIT_MS });
|
||||
const [statusFilter, setStatusFilter] = useState<"all" | GuardrailStatus>("all");
|
||||
const [selectedId, setSelectedId] = useState<string | null>(null);
|
||||
const [expandedHeaders, setExpandedHeaders] = useState<Set<string>>(new Set());
|
||||
|
|
@ -737,16 +740,10 @@ export function TeamGuardrailsTab({ accessToken }: TeamGuardrailsTabProps) {
|
|||
} | null>(null);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [searchDebounced, setSearchDebounced] = useState("");
|
||||
const [isSubmitModalOpen, setIsSubmitModalOpen] = useState(false);
|
||||
const [submitForm] = Form.useForm();
|
||||
const registerGuardrail = useRegisterGuardrail();
|
||||
|
||||
useEffect(() => {
|
||||
const t = setTimeout(() => setSearchDebounced(search), 300);
|
||||
return () => clearTimeout(t);
|
||||
}, [search]);
|
||||
|
||||
const fetchSubmissions = useCallback(async () => {
|
||||
if (!accessToken) {
|
||||
setIsLoading(false);
|
||||
|
|
|
|||
|
|
@ -14,11 +14,13 @@ import { useQueryClient } from "@tanstack/react-query";
|
|||
import { Grid, TabPanel } from "@tremor/react";
|
||||
import { Badge, Button, Select, Skeleton, Space, Typography } from "antd";
|
||||
import ModelSettingsModal from "@/components/model_dashboard/ModelSettingsModal/ModelSettingsModal";
|
||||
import debounce from "lodash/debounce";
|
||||
import { useDebouncedCallback } from "@tanstack/react-pacer/debouncer";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { useModelsInfo } from "../../hooks/models/useModels";
|
||||
import { transformModelData } from "../utils/modelDataTransformer";
|
||||
type ModelViewMode = "all" | "current_team";
|
||||
|
||||
const SEARCH_DEBOUNCE_WAIT_MS = 200;
|
||||
const { Text } = Typography;
|
||||
|
||||
interface AllModelsTabProps {
|
||||
|
|
@ -59,23 +61,17 @@ const AllModelsTab = ({
|
|||
const [sorting, setSorting] = useState<SortingState>([]);
|
||||
const [isModelSettingsModalVisible, setIsModelSettingsModalVisible] = useState(false);
|
||||
|
||||
// Debounce search input
|
||||
const debouncedUpdateSearch = useMemo(
|
||||
() =>
|
||||
debounce((value: string) => {
|
||||
setDebouncedSearch(value);
|
||||
// Reset to page 1 when search changes
|
||||
setCurrentPage(1);
|
||||
setPagination((prev: PaginationState) => ({ ...prev, pageIndex: 0 }));
|
||||
}, 200),
|
||||
[],
|
||||
const debouncedUpdateSearch = useDebouncedCallback(
|
||||
(value: string) => {
|
||||
setDebouncedSearch(value);
|
||||
setCurrentPage(1);
|
||||
setPagination((prev: PaginationState) => ({ ...prev, pageIndex: 0 }));
|
||||
},
|
||||
{ wait: SEARCH_DEBOUNCE_WAIT_MS },
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
debouncedUpdateSearch(modelNameSearch);
|
||||
return () => {
|
||||
debouncedUpdateSearch.cancel();
|
||||
};
|
||||
}, [modelNameSearch, debouncedUpdateSearch]);
|
||||
|
||||
// Determine teamId to pass to the query - only pass if not "personal"
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ import { A2ATaskMetadata, MessageType } from "@/components/chat_ui/types";
|
|||
import { useCodeInterpreter } from "../../hooks/useCodeInterpreter";
|
||||
import { useChatHistory } from "../../hooks/useChatHistory";
|
||||
import { getSecureItem, setSecureItem } from "@/utils/secureStorage";
|
||||
import { useDebouncedCallback } from "@tanstack/react-pacer/debouncer";
|
||||
|
||||
const { TextArea } = Input;
|
||||
const { Dragger } = Upload;
|
||||
|
|
@ -99,6 +100,8 @@ interface ChatUIProps {
|
|||
|
||||
const MCP_SUPPORTED_ENDPOINTS = new Set<EndpointType>([EndpointType.CHAT, EndpointType.RESPONSES, EndpointType.MCP]);
|
||||
|
||||
const CUSTOM_MODEL_DEBOUNCE_WAIT_MS = 500;
|
||||
|
||||
const ChatUI: React.FC<ChatUIProps> = ({
|
||||
accessToken,
|
||||
token,
|
||||
|
|
@ -185,7 +188,9 @@ const ChatUI: React.FC<ChatUIProps> = ({
|
|||
const [modelInfo, setModelInfo] = useState<ModelGroup[]>([]);
|
||||
const [agentInfo, setAgentInfo] = useState<Agent[]>([]);
|
||||
const [selectedAgent, setSelectedAgent] = useState<string | undefined>(undefined);
|
||||
const customModelTimeout = useRef<NodeJS.Timeout | null>(null);
|
||||
const debouncedSetSelectedModel = useDebouncedCallback((value: string) => setSelectedModel(value), {
|
||||
wait: CUSTOM_MODEL_DEBOUNCE_WAIT_MS,
|
||||
});
|
||||
const [endpointType, setEndpointType] = useState<string>(
|
||||
() => sessionStorage.getItem("endpointType") || EndpointType.CHAT,
|
||||
);
|
||||
|
|
@ -1255,16 +1260,7 @@ const ChatUI: React.FC<ChatUIProps> = ({
|
|||
<TextInput
|
||||
className="mt-2"
|
||||
placeholder="Enter custom model name"
|
||||
onValueChange={(value) => {
|
||||
// Using setTimeout to create a simple debounce effect
|
||||
if (customModelTimeout.current) {
|
||||
clearTimeout(customModelTimeout.current);
|
||||
}
|
||||
|
||||
customModelTimeout.current = setTimeout(() => {
|
||||
setSelectedModel(value);
|
||||
}, 500); // 500ms delay after typing stops
|
||||
}}
|
||||
onValueChange={debouncedSetSelectedModel}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
"use client";
|
||||
|
||||
import NotificationsManager from "@/components/molecules/notifications_manager";
|
||||
import { DEBOUNCE_WAIT_MS } from "@/utils/debounceConstants";
|
||||
import { ClearOutlined, DeleteOutlined, FilePdfOutlined, PlusOutlined } from "@ant-design/icons";
|
||||
import { useDebouncedValue } from "@tanstack/react-pacer/debouncer";
|
||||
import { Button, Input, Select, Tooltip } from "antd";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
|
|
@ -105,14 +107,8 @@ export default function CompareUI({ accessToken, disabledPersonalKeyCreation }:
|
|||
disabledPersonalKeyCreation ? "custom" : "session",
|
||||
);
|
||||
const [customApiKey, setCustomApiKey] = useState("");
|
||||
const [debouncedCustomApiKey, setDebouncedCustomApiKey] = useState("");
|
||||
const [debouncedCustomApiKey] = useDebouncedValue(customApiKey, { wait: DEBOUNCE_WAIT_MS });
|
||||
const [customProxyBaseUrl] = useState<string>(() => sessionStorage.getItem("customProxyBaseUrl") || "");
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => {
|
||||
setDebouncedCustomApiKey(customApiKey);
|
||||
}, 300);
|
||||
return () => clearTimeout(timer);
|
||||
}, [customApiKey]);
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (uploadedFilePreviewUrl) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue