mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-15 01:54:52 +01:00
Fix broken React usage with dropdowns causing unnecessary re-renders in preferences (#95904)
Fixes https://github.com/tgstation/tgstation/issues/95860#issuecomment-4320548139. Thank you to @leaKsi for isolating it React lints would've caught this--components not being components'd properly and then an inline callback ended up causing a bunch of re-renders. I didn't test shit --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
+26
-12
@@ -1,7 +1,9 @@
|
||||
import { useCallback } from 'react';
|
||||
import { Gender } from '../../gender';
|
||||
import type { FeatureChoiced } from '../base';
|
||||
import type { FeatureChoicedServerData, FeatureChoiced } from '../base';
|
||||
import {
|
||||
type DropdownInputProps,
|
||||
type DropdownOptions,
|
||||
FeatureDropdownInputCore,
|
||||
generateOptions,
|
||||
} from '../dropdowns';
|
||||
@@ -12,17 +14,29 @@ export const body_type: FeatureChoiced = {
|
||||
};
|
||||
|
||||
function FeatureBodyTypeDropdownInput(props: DropdownInputProps) {
|
||||
return FeatureDropdownInputCore(props, (serverData, setDropdownOptions) => {
|
||||
let options = generateOptions(serverData);
|
||||
const currentGender = props.character_preferences.misc.gender;
|
||||
|
||||
const current_gender = props.character_preferences.misc.gender;
|
||||
if (current_gender !== Gender.Male && current_gender !== Gender.Female) {
|
||||
options = options.filter(
|
||||
(option) =>
|
||||
option.value === Gender.Male || option.value === Gender.Female,
|
||||
);
|
||||
}
|
||||
const populateOptions = useCallback(
|
||||
(
|
||||
serverData: FeatureChoicedServerData,
|
||||
setDropdownOptions: (newValue: DropdownOptions) => void
|
||||
) => {
|
||||
let options = generateOptions(serverData);
|
||||
|
||||
setDropdownOptions(options);
|
||||
});
|
||||
if (currentGender !== Gender.Male && currentGender !== Gender.Female) {
|
||||
options = options.filter(
|
||||
(option) =>
|
||||
option.value === Gender.Male || option.value === Gender.Female,
|
||||
);
|
||||
}
|
||||
|
||||
setDropdownOptions(options);
|
||||
},
|
||||
[currentGender],
|
||||
);
|
||||
|
||||
return <FeatureDropdownInputCore
|
||||
dropdownProps={props}
|
||||
populateOptions={populateOptions}
|
||||
/>
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import {
|
||||
type ComponentProps,
|
||||
type ReactNode,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useState,
|
||||
} from 'react';
|
||||
@@ -32,7 +33,7 @@ type IconnedDropdownInputProps = FeatureValueProps<
|
||||
|
||||
export type FeatureWithIcons<T> = Feature<string, T, FeatureChoicedServerData>;
|
||||
|
||||
type DropdownOptions = ComponentProps<typeof Dropdown>['options'];
|
||||
export type DropdownOptions = ComponentProps<typeof Dropdown>['options'];
|
||||
|
||||
type DropdownEntry = {
|
||||
displayText: ReactNode;
|
||||
@@ -60,20 +61,20 @@ export function generateOptions(
|
||||
return newOptions;
|
||||
}
|
||||
|
||||
export function FeatureDropdownInput(props: DropdownInputProps) {
|
||||
return FeatureDropdownInputCore(props, (serverData, setDropdownOptions) =>
|
||||
setDropdownOptions(generateOptions(serverData)),
|
||||
);
|
||||
}
|
||||
|
||||
export function FeatureDropdownInputCore(
|
||||
props: DropdownInputProps,
|
||||
export type FeatureDropdownInputCoreProps = {
|
||||
dropdownProps: DropdownInputProps,
|
||||
populateOptions: (
|
||||
serverData: FeatureChoicedServerData,
|
||||
setDropdownOptions: (newValue: DropdownOptions) => void,
|
||||
) => void,
|
||||
}
|
||||
|
||||
export function FeatureDropdownInputCore(
|
||||
props: FeatureDropdownInputCoreProps
|
||||
) {
|
||||
const { serverData, disabled, buttons, handleSetValue, value } = props;
|
||||
const { dropdownProps, populateOptions } = props;
|
||||
const { serverData, disabled, buttons, handleSetValue, value } =
|
||||
dropdownProps;
|
||||
|
||||
const [dropdownOptions, setDropdownOptions] = useState<DropdownOptions>([]);
|
||||
|
||||
@@ -98,6 +99,23 @@ export function FeatureDropdownInputCore(
|
||||
);
|
||||
}
|
||||
|
||||
export function FeatureDropdownInput(props: DropdownInputProps) {
|
||||
const populateOptions = useCallback(
|
||||
(
|
||||
serverData: FeatureChoicedServerData,
|
||||
setDropdownOptions: (newValue: DropdownOptions) => void
|
||||
) => {
|
||||
setDropdownOptions(generateOptions(serverData));
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
return <FeatureDropdownInputCore
|
||||
dropdownProps={props}
|
||||
populateOptions={populateOptions}
|
||||
/>
|
||||
}
|
||||
|
||||
export function FeatureIconnedDropdownInput(props: IconnedDropdownInputProps) {
|
||||
const { serverData, handleSetValue, value } = props;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user