🐛 fix: Resolve 'Icon is Not a Function' Error in PresetItems (#5260)

* refactor: improve typing

* fix: "TypeError: Icon is not a function" with proper use of Functional Component and Improved Typing
This commit is contained in:
Danny Avila 2025-01-10 19:00:44 -05:00 committed by GitHub
parent 0855677a36
commit 24beda3d69
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 57 additions and 49 deletions

View file

@ -1,5 +1,5 @@
import { EModelEndpoint } from 'librechat-data-provider';
import type { IconMapProps, AgentIconMapProps } from '~/common';
import type { IconMapProps, AgentIconMapProps, IconsRecord } from '~/common';
import { Feather } from 'lucide-react';
import {
MinimalPlugin,
@ -42,7 +42,7 @@ const AssistantAvatar = ({
};
const AgentAvatar = ({ className = '', avatar = '', agentName, size }: AgentIconMapProps) => {
if (agentName && avatar) {
if (agentName != null && agentName && avatar) {
return (
<img
src={avatar}
@ -61,7 +61,7 @@ const Bedrock = ({ className = '' }: IconMapProps) => {
return <BedrockIcon className={cn(className, 'h-full w-full')} />;
};
export const icons = {
export const icons: IconsRecord = {
[EModelEndpoint.azureOpenAI]: AzureMinimalIcon,
[EModelEndpoint.openAI]: GPTIcon,
[EModelEndpoint.gptPlugins]: MinimalPlugin,

View file

@ -16,7 +16,7 @@ import { cn } from '~/utils';
import store from '~/store';
const PresetItems: FC<{
presets: TPreset[];
presets?: Array<TPreset | undefined>;
onSetDefaultPreset: (preset: TPreset, remove?: boolean) => void;
onSelectPreset: (preset: TPreset) => void;
onChangePreset: (preset: TPreset) => void;
@ -110,11 +110,17 @@ const PresetItems: FC<{
</div>
</div>
)}
<Flipper flipKey={presets.map(({ presetId }) => presetId).join('.')}>
<Flipper
flipKey={presets
?.map((preset) => preset?.presetId)
.filter((p) => p)
.join('.')}
>
{presets &&
presets.length > 0 &&
presets.map((preset, i) => {
if (!preset || !preset.presetId) {
const presetId = preset?.presetId ?? '';
if (!preset || !presetId) {
return null;
}
@ -122,22 +128,23 @@ const PresetItems: FC<{
const Icon = icons[iconKey];
return (
<Close asChild key={`preset-${preset.presetId}`}>
<div key={`preset-${preset.presetId}`}>
<Flipped flipId={preset.presetId}>
<Close asChild key={`preset-${presetId}`}>
<div key={`preset-${presetId}`}>
<Flipped flipId={presetId}>
<MenuItem
key={`preset-item-${preset.presetId}`}
key={`preset-item-${presetId}`}
textClassName="text-xs max-w-[150px] sm:max-w-[200px] truncate md:max-w-full "
title={getPresetTitle(preset)}
onClick={() => onSelectPreset(preset)}
icon={
Icon &&
Icon({
context: 'menu-item',
iconURL: getEndpointField(endpointsConfig, preset.endpoint, 'iconURL'),
className: 'icon-md mr-1 dark:text-white',
endpoint: preset.endpoint,
})
Icon != null && (
<Icon
context="menu-item"
iconURL={getEndpointField(endpointsConfig, preset.endpoint, 'iconURL')}
className="icon-md mr-1 dark:text-white"
endpoint={preset.endpoint}
/>
)
}
selected={false}
data-testid={`preset-item-${preset}`}
@ -146,17 +153,17 @@ const PresetItems: FC<{
<button
className={cn(
'm-0 h-full rounded-md bg-transparent p-2 text-gray-400 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200',
defaultPreset?.presetId === preset.presetId
defaultPreset?.presetId === presetId
? ''
: 'sm:invisible sm:group-hover:visible',
)}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
onSetDefaultPreset(preset, defaultPreset?.presetId === preset.presetId);
onSetDefaultPreset(preset, defaultPreset?.presetId === presetId);
}}
>
<PinIcon unpin={defaultPreset?.presetId === preset.presetId} />
<PinIcon unpin={defaultPreset?.presetId === presetId} />
</button>
<button
className="m-0 h-full rounded-md p-2 text-gray-400 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200 sm:invisible sm:group-hover:visible"

View file

@ -20,8 +20,6 @@ const PresetsMenu: FC = () => {
exportPreset,
} = usePresets();
const { preset } = useChatContext();
const presets = presetsQuery.data || [];
return (
<Root>
<Trigger asChild>
@ -54,7 +52,7 @@ const PresetsMenu: FC = () => {
className="mt-2 max-h-[495px] overflow-x-hidden rounded-lg border border-gray-200 bg-white shadow-lg dark:border-gray-700 dark:bg-gray-700 dark:text-white md:min-w-[400px]"
>
<PresetItems
presets={presets}
presets={presetsQuery.data}
onSetDefaultPreset={onSetDefaultPreset}
onSelectPreset={onSelectPreset}
onChangePreset={onChangePreset}