mirror of
https://github.com/langchain-ai/openwork.git
synced 2026-07-18 20:54:26 -04:00
Fix ModelSwitcher to derive selectedProviderId instead of setState in effect
Replace the problematic useEffect that set state synchronously with a useMemo that derives the selected provider. This eliminates the double render and satisfies the react-hooks/set-state-in-effect rule without needing eslint-disable. Changes: - Renamed selectedProviderId state to manuallySelectedProviderId - Use useMemo to derive selectedProviderId from: 1. Manual selection (if user clicked a provider) 2. Current model's provider (if a model is selected) 3. First available provider (as fallback) - No more setState in useEffect = no cascading renders
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useState, useEffect } from 'react'
|
||||
import { useState, useEffect, useMemo } from 'react'
|
||||
import { ChevronDown, Check, AlertCircle, Key } from 'lucide-react'
|
||||
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'
|
||||
import { Button } from '@/components/ui/button'
|
||||
@@ -53,7 +53,9 @@ interface ModelSwitcherProps {
|
||||
|
||||
export function ModelSwitcher({ threadId }: ModelSwitcherProps): React.JSX.Element {
|
||||
const [open, setOpen] = useState(false)
|
||||
const [selectedProviderId, setSelectedProviderId] = useState<ProviderId | null>(null)
|
||||
const [manuallySelectedProviderId, setManuallySelectedProviderId] = useState<ProviderId | null>(
|
||||
null
|
||||
)
|
||||
const [apiKeyDialogOpen, setApiKeyDialogOpen] = useState(false)
|
||||
const [apiKeyProvider, setApiKeyProvider] = useState<Provider | null>(null)
|
||||
|
||||
@@ -69,20 +71,22 @@ export function ModelSwitcher({ threadId }: ModelSwitcherProps): React.JSX.Eleme
|
||||
// Use fallback providers if none loaded
|
||||
const displayProviders = providers.length > 0 ? providers : FALLBACK_PROVIDERS
|
||||
|
||||
// Set initial selected provider based on current model
|
||||
useEffect(() => {
|
||||
if (!selectedProviderId && currentModel) {
|
||||
// Derive the selected provider from current model or manual selection
|
||||
const selectedProviderId = useMemo(() => {
|
||||
// If user manually selected a provider, use that
|
||||
if (manuallySelectedProviderId) {
|
||||
return manuallySelectedProviderId
|
||||
}
|
||||
// Otherwise, derive from current model
|
||||
if (currentModel) {
|
||||
const model = models.find((m) => m.id === currentModel)
|
||||
if (model) {
|
||||
// eslint-disable-next-line react-hooks/set-state-in-effect
|
||||
setSelectedProviderId(model.provider)
|
||||
return model.provider
|
||||
}
|
||||
}
|
||||
// Default to first provider if none selected
|
||||
if (!selectedProviderId && displayProviders.length > 0) {
|
||||
setSelectedProviderId(displayProviders[0].id)
|
||||
}
|
||||
}, [currentModel, models, selectedProviderId, displayProviders])
|
||||
// Default to first provider
|
||||
return displayProviders[0]?.id || null
|
||||
}, [manuallySelectedProviderId, currentModel, models, displayProviders])
|
||||
|
||||
const selectedModel = models.find((m) => m.id === currentModel)
|
||||
const filteredModels = selectedProviderId
|
||||
@@ -91,7 +95,7 @@ export function ModelSwitcher({ threadId }: ModelSwitcherProps): React.JSX.Eleme
|
||||
const selectedProvider = displayProviders.find((p) => p.id === selectedProviderId)
|
||||
|
||||
function handleProviderClick(provider: Provider): void {
|
||||
setSelectedProviderId(provider.id)
|
||||
setManuallySelectedProviderId(provider.id)
|
||||
}
|
||||
|
||||
function handleModelSelect(modelId: string): void {
|
||||
|
||||
Reference in New Issue
Block a user