Skip to content

Commit 987e401

Browse files
perf(ui): lora components
1 parent 5c5ac57 commit 987e401

File tree

3 files changed

+38
-20
lines changed

3 files changed

+38
-20
lines changed

invokeai/frontend/web/src/features/lora/components/LoRACard.tsx

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,38 @@ import {
99
Switch,
1010
Text,
1111
} from '@invoke-ai/ui-library';
12-
import { useAppDispatch } from 'app/store/storeHooks';
12+
import { createSelector } from '@reduxjs/toolkit';
13+
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
1314
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
14-
import { loraDeleted, loraIsEnabledChanged, loraWeightChanged } from 'features/controlLayers/store/lorasSlice';
15+
import {
16+
loraDeleted,
17+
loraIsEnabledChanged,
18+
loraWeightChanged,
19+
selectLoRAsSlice,
20+
} from 'features/controlLayers/store/lorasSlice';
1521
import type { LoRA } from 'features/controlLayers/store/types';
16-
import { memo, useCallback } from 'react';
22+
import { memo, useCallback, useMemo } from 'react';
1723
import { PiTrashSimpleBold } from 'react-icons/pi';
1824
import { useGetModelConfigQuery } from 'services/api/endpoints/models';
1925

20-
type LoRACardProps = {
21-
lora: LoRA;
22-
};
23-
2426
const marks = [-1, 0, 1, 2];
2527

26-
export const LoRACard = memo((props: LoRACardProps) => {
27-
const { lora } = props;
28+
export const LoRACard = memo((props: { id: string }) => {
29+
const selectLoRA = useMemo(
30+
() => createSelector(selectLoRAsSlice, ({ loras }) => loras.find(({ id }) => id === props.id)),
31+
[props.id]
32+
);
33+
const lora = useAppSelector(selectLoRA);
34+
35+
if (!lora) {
36+
return null;
37+
}
38+
return <LoRAContent lora={lora} />;
39+
});
40+
41+
LoRACard.displayName = 'LoRACard';
42+
43+
export const LoRAContent = memo(({ lora }: { lora: LoRA }) => {
2844
const dispatch = useAppDispatch();
2945
const { data: loraConfig } = useGetModelConfigQuery(lora.model.key);
3046

@@ -91,4 +107,4 @@ export const LoRACard = memo((props: LoRACardProps) => {
91107
);
92108
});
93109

94-
LoRACard.displayName = 'LoRACard';
110+
LoRAContent.displayName = 'LoRAContent';

invokeai/frontend/web/src/features/lora/components/LoRAList.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,19 @@ import { selectLoRAsSlice } from 'features/controlLayers/store/lorasSlice';
55
import { LoRACard } from 'features/lora/components/LoRACard';
66
import { memo } from 'react';
77

8-
const selectLoRAsArray = createMemoizedSelector(selectLoRAsSlice, (loras) => loras.loras);
8+
const selectLoRAIds = createMemoizedSelector(selectLoRAsSlice, (loras) => loras.loras.map(({ id }) => id));
99

1010
export const LoRAList = memo(() => {
11-
const lorasArray = useAppSelector(selectLoRAsArray);
11+
const ids = useAppSelector(selectLoRAIds);
1212

13-
if (!lorasArray.length) {
13+
if (!ids.length) {
1414
return null;
1515
}
1616

1717
return (
1818
<Flex flexWrap="wrap" gap={2}>
19-
{lorasArray.map((lora) => (
20-
<LoRACard key={lora.id} lora={lora} />
19+
{ids.map((id) => (
20+
<LoRACard key={id} id={id} />
2121
))}
2222
</Flex>
2323
);

invokeai/frontend/web/src/features/lora/components/LoRASelect.tsx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { FormControl, FormLabel } from '@invoke-ai/ui-library';
2-
import { createSelector } from '@reduxjs/toolkit';
32
import { EMPTY_ARRAY } from 'app/store/constants';
3+
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
44
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
55
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
66
import type { GroupStatusMap } from 'common/components/Picker/Picker';
@@ -13,13 +13,15 @@ import { useTranslation } from 'react-i18next';
1313
import { useLoRAModels } from 'services/api/hooks/modelsByType';
1414
import type { LoRAModelConfig } from 'services/api/types';
1515

16-
const selectLoRAs = createSelector(selectLoRAsSlice, (loras) => loras.loras);
16+
const selectLoRAModelKeys = createMemoizedSelector(selectLoRAsSlice, ({ loras }) =>
17+
loras.map(({ model }) => model.key)
18+
);
1719

1820
const LoRASelect = () => {
1921
const dispatch = useAppDispatch();
2022
const [modelConfigs, { isLoading }] = useLoRAModels();
2123
const { t } = useTranslation();
22-
const addedLoRAs = useAppSelector(selectLoRAs);
24+
const addedLoRAModelKeys = useAppSelector(selectLoRAModelKeys);
2325

2426
const currentBaseModel = useAppSelector(selectBase);
2527

@@ -33,10 +35,10 @@ const LoRASelect = () => {
3335

3436
const getIsDisabled = useCallback(
3537
(model: LoRAModelConfig): boolean => {
36-
const isAdded = Boolean(addedLoRAs.find((lora) => lora.model.key === model.key));
38+
const isAdded = addedLoRAModelKeys.includes(model.key);
3739
return isAdded;
3840
},
39-
[addedLoRAs]
41+
[addedLoRAModelKeys]
4042
);
4143

4244
const onChange = useCallback(

0 commit comments

Comments
 (0)