mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
fix: debounce slider to avoid laggy behavior (#18980)
resolves #18856 resolves coder/internal#753
This commit is contained in:
@@ -77,14 +77,14 @@ export const DynamicParameter: FC<DynamicParameterProps> = ({
|
||||
/>
|
||||
<div className="max-w-lg">
|
||||
{parameter.form_type === "input" ||
|
||||
parameter.form_type === "textarea" ? (
|
||||
parameter.form_type === "textarea" ||
|
||||
parameter.form_type === "slider" ? (
|
||||
<DebouncedParameterField
|
||||
id={id}
|
||||
parameter={parameter}
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
disabled={disabled}
|
||||
isPreset={isPreset}
|
||||
/>
|
||||
) : (
|
||||
<ParameterField
|
||||
@@ -250,7 +250,6 @@ interface DebouncedParameterFieldProps {
|
||||
onChange: (value: string) => void;
|
||||
disabled?: boolean;
|
||||
id: string;
|
||||
isPreset?: boolean;
|
||||
}
|
||||
|
||||
const DebouncedParameterField: FC<DebouncedParameterFieldProps> = ({
|
||||
@@ -259,7 +258,6 @@ const DebouncedParameterField: FC<DebouncedParameterFieldProps> = ({
|
||||
onChange,
|
||||
disabled,
|
||||
id,
|
||||
isPreset,
|
||||
}) => {
|
||||
const [localValue, setLocalValue] = useState(
|
||||
value !== undefined ? value : validValue(parameter.value),
|
||||
@@ -271,13 +269,13 @@ const DebouncedParameterField: FC<DebouncedParameterFieldProps> = ({
|
||||
const prevDebouncedValueRef = useRef<string | undefined>();
|
||||
const prevValueRef = useRef(value);
|
||||
|
||||
// This is necessary in the case of fields being set by preset parameters
|
||||
// Necessary for dynamic defaults or fields being set by preset parameters
|
||||
useEffect(() => {
|
||||
if (isPreset && value !== undefined && value !== prevValueRef.current) {
|
||||
if (value !== undefined && value !== prevValueRef.current) {
|
||||
setLocalValue(value);
|
||||
prevValueRef.current = value;
|
||||
}
|
||||
}, [value, isPreset]);
|
||||
}, [value]);
|
||||
|
||||
useEffect(() => {
|
||||
// Only call onChangeEvent if debouncedLocalValue is different from the previously committed value
|
||||
@@ -408,6 +406,31 @@ const DebouncedParameterField: FC<DebouncedParameterFieldProps> = ({
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
case "slider": {
|
||||
const numericValue = Number.isFinite(Number(localValue))
|
||||
? Number(localValue)
|
||||
: 0;
|
||||
const { validation_min: min = 0, validation_max: max = 100 } =
|
||||
parameter.validations[0] ?? {};
|
||||
|
||||
return (
|
||||
<div className="flex flex-row items-baseline gap-3">
|
||||
<Slider
|
||||
id={id}
|
||||
className="mt-2"
|
||||
value={[numericValue]}
|
||||
onValueChange={([value]) => {
|
||||
setLocalValue(value.toString());
|
||||
}}
|
||||
min={min ?? undefined}
|
||||
max={max ?? undefined}
|
||||
disabled={disabled}
|
||||
/>
|
||||
<span className="w-4 font-medium">{numericValue}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -564,25 +587,6 @@ const ParameterField: FC<ParameterFieldProps> = ({
|
||||
</div>
|
||||
);
|
||||
|
||||
case "slider":
|
||||
return (
|
||||
<div className="flex flex-row items-baseline gap-3">
|
||||
<Slider
|
||||
id={id}
|
||||
className="mt-2"
|
||||
value={[Number.isFinite(Number(value)) ? Number(value) : 0]}
|
||||
onValueChange={([value]) => {
|
||||
onChange(value.toString());
|
||||
}}
|
||||
min={parameter.validations[0]?.validation_min ?? 0}
|
||||
max={parameter.validations[0]?.validation_max ?? 100}
|
||||
disabled={disabled}
|
||||
/>
|
||||
<span className="w-4 font-medium">
|
||||
{Number.isFinite(Number(value)) ? value : "0"}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
case "error":
|
||||
return <Diagnostics diagnostics={parameter.diagnostics} />;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user