diff --git a/invokeai/frontend/web/src/features/lora/components/LoRACard.tsx b/invokeai/frontend/web/src/features/lora/components/LoRACard.tsx
index 28c0ea8198..dd26a8e73b 100644
--- a/invokeai/frontend/web/src/features/lora/components/LoRACard.tsx
+++ b/invokeai/frontend/web/src/features/lora/components/LoRACard.tsx
@@ -9,22 +9,38 @@ import {
Switch,
Text,
} from '@invoke-ai/ui-library';
-import { useAppDispatch } from 'app/store/storeHooks';
+import { createSelector } from '@reduxjs/toolkit';
+import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
-import { loraDeleted, loraIsEnabledChanged, loraWeightChanged } from 'features/controlLayers/store/lorasSlice';
+import {
+ loraDeleted,
+ loraIsEnabledChanged,
+ loraWeightChanged,
+ selectLoRAsSlice,
+} from 'features/controlLayers/store/lorasSlice';
import type { LoRA } from 'features/controlLayers/store/types';
-import { memo, useCallback } from 'react';
+import { memo, useCallback, useMemo } from 'react';
import { PiTrashSimpleBold } from 'react-icons/pi';
import { useGetModelConfigQuery } from 'services/api/endpoints/models';
-type LoRACardProps = {
- lora: LoRA;
-};
-
const marks = [-1, 0, 1, 2];
-export const LoRACard = memo((props: LoRACardProps) => {
- const { lora } = props;
+export const LoRACard = memo((props: { id: string }) => {
+ const selectLoRA = useMemo(
+ () => createSelector(selectLoRAsSlice, ({ loras }) => loras.find(({ id }) => id === props.id)),
+ [props.id]
+ );
+ const lora = useAppSelector(selectLoRA);
+
+ if (!lora) {
+ return null;
+ }
+ return ;
+});
+
+LoRACard.displayName = 'LoRACard';
+
+export const LoRAContent = memo(({ lora }: { lora: LoRA }) => {
const dispatch = useAppDispatch();
const { data: loraConfig } = useGetModelConfigQuery(lora.model.key);
@@ -91,4 +107,4 @@ export const LoRACard = memo((props: LoRACardProps) => {
);
});
-LoRACard.displayName = 'LoRACard';
+LoRAContent.displayName = 'LoRAContent';
diff --git a/invokeai/frontend/web/src/features/lora/components/LoRAList.tsx b/invokeai/frontend/web/src/features/lora/components/LoRAList.tsx
index 6d05f1ea6f..5e43ab9223 100644
--- a/invokeai/frontend/web/src/features/lora/components/LoRAList.tsx
+++ b/invokeai/frontend/web/src/features/lora/components/LoRAList.tsx
@@ -5,19 +5,19 @@ import { selectLoRAsSlice } from 'features/controlLayers/store/lorasSlice';
import { LoRACard } from 'features/lora/components/LoRACard';
import { memo } from 'react';
-const selectLoRAsArray = createMemoizedSelector(selectLoRAsSlice, (loras) => loras.loras);
+const selectLoRAIds = createMemoizedSelector(selectLoRAsSlice, (loras) => loras.loras.map(({ id }) => id));
export const LoRAList = memo(() => {
- const lorasArray = useAppSelector(selectLoRAsArray);
+ const ids = useAppSelector(selectLoRAIds);
- if (!lorasArray.length) {
+ if (!ids.length) {
return null;
}
return (
- {lorasArray.map((lora) => (
-
+ {ids.map((id) => (
+
))}
);
diff --git a/invokeai/frontend/web/src/features/lora/components/LoRASelect.tsx b/invokeai/frontend/web/src/features/lora/components/LoRASelect.tsx
index c9a5f2f846..01c9cffc36 100644
--- a/invokeai/frontend/web/src/features/lora/components/LoRASelect.tsx
+++ b/invokeai/frontend/web/src/features/lora/components/LoRASelect.tsx
@@ -1,6 +1,6 @@
import { FormControl, FormLabel } from '@invoke-ai/ui-library';
-import { createSelector } from '@reduxjs/toolkit';
import { EMPTY_ARRAY } from 'app/store/constants';
+import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
import type { GroupStatusMap } from 'common/components/Picker/Picker';
@@ -13,13 +13,15 @@ import { useTranslation } from 'react-i18next';
import { useLoRAModels } from 'services/api/hooks/modelsByType';
import type { LoRAModelConfig } from 'services/api/types';
-const selectLoRAs = createSelector(selectLoRAsSlice, (loras) => loras.loras);
+const selectLoRAModelKeys = createMemoizedSelector(selectLoRAsSlice, ({ loras }) =>
+ loras.map(({ model }) => model.key)
+);
const LoRASelect = () => {
const dispatch = useAppDispatch();
const [modelConfigs, { isLoading }] = useLoRAModels();
const { t } = useTranslation();
- const addedLoRAs = useAppSelector(selectLoRAs);
+ const addedLoRAModelKeys = useAppSelector(selectLoRAModelKeys);
const currentBaseModel = useAppSelector(selectBase);
@@ -33,10 +35,10 @@ const LoRASelect = () => {
const getIsDisabled = useCallback(
(model: LoRAModelConfig): boolean => {
- const isAdded = Boolean(addedLoRAs.find((lora) => lora.model.key === model.key));
+ const isAdded = addedLoRAModelKeys.includes(model.key);
return isAdded;
},
- [addedLoRAs]
+ [addedLoRAModelKeys]
);
const onChange = useCallback(