Skip to content

Commit b4994f4

Browse files
committed
fix(form): Added fixes required for Concurrent Rendering
1 parent ff8a1d6 commit b4994f4

8 files changed

Lines changed: 72 additions & 47 deletions

File tree

packages/form/src/select/Listbox.tsx

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
import { forwardRef, HTMLAttributes, useCallback, useRef } from "react";
1+
import {
2+
forwardRef,
3+
HTMLAttributes,
4+
useCallback,
5+
useEffect,
6+
useRef,
7+
} from "react";
28
import cn from "classnames";
39
import { List, ListElement } from "@react-md/list";
410
import {
@@ -360,14 +366,18 @@ export const Listbox = forwardRef<ListElement, ListboxProps>(function Listbox(
360366
});
361367

362368
const prevVisible = useRef(visible);
363-
if (visible !== prevVisible.current) {
369+
useEffect(() => {
370+
if (prevVisible.current === visible) {
371+
return;
372+
}
373+
364374
prevVisible.current = visible;
365375
// whenever it gains visibility, try to set the focused index to the
366376
// current active value
367377
if (visible) {
368378
setFocusedIndex(getIndex());
369379
}
370-
}
380+
}, [getIndex, setFocusedIndex, visible]);
371381

372382
const handleFocus = useCallback(
373383
(event: React.FocusEvent<ListElement>) => {

packages/form/src/slider/useDiscreteValueVisibility.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,6 @@ export function useDiscreteValueVisibility({
7272
// immediately
7373
const [isModeTransition, setModeTransition] = useState(false);
7474
const [visible, setVisible] = useState(false);
75-
if (discrete && visible && disabled) {
76-
setVisible(false);
77-
}
7875

7976
useEffect(() => {
8077
if (!discrete) {
@@ -83,6 +80,11 @@ export function useDiscreteValueVisibility({
8380
return;
8481
}
8582

83+
if (discrete && visible && disabled) {
84+
setVisible(false);
85+
return;
86+
}
87+
8688
if (!isKeyboard) {
8789
// only considered a "transition" when the tooltip is already visible and
8890
// switching away from keyboard mode
@@ -96,8 +98,8 @@ export function useDiscreteValueVisibility({
9698
// the user switch between the modes more easily so if the active element is
9799
// the current thumb, we're good to go
98100
setModeTransition(false);
99-
setVisible(document.activeElement === ref.current);
100-
}, [isKeyboard, visible, discrete]);
101+
setVisible(!disabled && document.activeElement === ref.current);
102+
}, [isKeyboard, visible, discrete, disabled]);
101103

102104
useEffect(() => {
103105
if (!discrete) {

packages/form/src/slider/useRangeSlider.ts

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useCallback, useMemo, useRef, useState } from "react";
1+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
22
import { nearest } from "@react-md/utils";
33

44
import {
@@ -197,23 +197,25 @@ export function useRangeSlider(
197197
}, [onChange, value]);
198198

199199
const prev = useRef({ min, max, step });
200-
if (
201-
prev.current.min !== min ||
202-
prev.current.max !== max ||
203-
prev.current.step !== step
204-
) {
205-
// ensure that if the `min`, `max`, or `step` value changes that the value
206-
// is updated as well. Without this, there will be a runtime error if the
207-
// value is not within the new range.
208-
prev.current = { min, max, step };
209-
const steps = getSteps(min, max, step);
210-
const nextValue: RangeSliderValue = [
211-
nearest(value[0], min, max, steps),
212-
nearest(value[1], min, max, steps),
213-
];
214-
currentValue.current = nextValue;
215-
setValue(nextValue);
216-
}
200+
useEffect(() => {
201+
if (
202+
prev.current.min !== min ||
203+
prev.current.max !== max ||
204+
prev.current.step !== step
205+
) {
206+
// ensure that if the `min`, `max`, or `step` value changes that the value
207+
// is updated as well. Without this, there will be a runtime error if the
208+
// value is not within the new range.
209+
prev.current = { min, max, step };
210+
const steps = getSteps(min, max, step);
211+
const nextValue: RangeSliderValue = [
212+
nearest(value[0], min, max, steps),
213+
nearest(value[1], min, max, steps),
214+
];
215+
currentValue.current = nextValue;
216+
setValue(nextValue);
217+
}
218+
}, [min, max, step, value]);
217219

218220
if (updateOn === "change" && currentValue.current !== value) {
219221
currentValue.current = value;

packages/form/src/slider/useSlider.ts

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useCallback, useMemo, useRef, useState } from "react";
1+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
22
import { nearest } from "@react-md/utils";
33

44
import {
@@ -116,19 +116,21 @@ export function useSlider(
116116
}, [onChange, value]);
117117

118118
const prev = useRef({ min, max, step });
119-
if (
120-
prev.current.min !== min ||
121-
prev.current.max !== max ||
122-
prev.current.step !== step
123-
) {
124-
// ensure that if the `min`, `max`, or `step` value changes that the value
125-
// is updated as well. Without this, there will be a runtime error if the
126-
// value is not within the new range.
127-
prev.current = { min, max, step };
128-
const nextValue = nearest(value, min, max, getSteps(min, max, step));
129-
currentValue.current = nextValue;
130-
setValue(nextValue);
131-
}
119+
useEffect(() => {
120+
if (
121+
prev.current.min !== min ||
122+
prev.current.max !== max ||
123+
prev.current.step !== step
124+
) {
125+
// ensure that if the `min`, `max`, or `step` value changes that the value
126+
// is updated as well. Without this, there will be a runtime error if the
127+
// value is not within the new range.
128+
prev.current = { min, max, step };
129+
const nextValue = nearest(value, min, max, getSteps(min, max, step));
130+
currentValue.current = nextValue;
131+
setValue(nextValue);
132+
}
133+
}, [min, max, step, value]);
132134

133135
if (updateOn === "change" && currentValue.current !== value) {
134136
currentValue.current = value;

packages/form/src/slider/utils.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,7 @@ export const getDragPercentage = ({
252252
min,
253253
max,
254254
value: thumb1Value,
255+
validate: false,
255256
});
256257

257258
let thumb2Percentage: number | undefined;
@@ -260,6 +261,7 @@ export const getDragPercentage = ({
260261
min,
261262
max,
262263
value: thumb2Value,
264+
validate: false,
263265
});
264266
thumb1Percentage = Math.min(thumb1Percentage, percentage);
265267
thumb2Percentage =

packages/form/src/text-field/TextArea.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
Ref,
88
TextareaHTMLAttributes,
99
useCallback,
10+
useEffect,
1011
useRef,
1112
useState,
1213
} from "react";
@@ -171,9 +172,11 @@ export const TextArea = forwardRef<HTMLTextAreaElement, TextAreaProps>(
171172
});
172173

173174
const [height, setHeight] = useState<number>();
174-
if (resize !== "auto" && typeof height === "number") {
175-
setHeight(undefined);
176-
}
175+
useEffect(() => {
176+
if (resize !== "auto" && typeof height === "number") {
177+
setHeight(undefined);
178+
}
179+
}, [resize, height]);
177180

178181
const maskRef = useRef<HTMLTextAreaElement | null>(null);
179182
const [scrollable, setScrollable] = useState(false);

packages/form/src/text-field/__tests__/__snapshots__/TextArea.tsx.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ exports[`TextArea should handle updating the height correctly based on the resiz
4848
data-testid="container"
4949
id="text-area"
5050
rows="2"
51+
style=""
5152
/>
5253
</div>
5354
`;

packages/form/src/useFieldStates.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
FocusEvent,
55
FocusEventHandler,
66
useCallback,
7+
useEffect,
78
useRef,
89
useState,
910
} from "react";
@@ -129,10 +130,12 @@ export function useFieldStates<E extends FormElement>({
129130
// `useNumberField` hook since the `value` will be set back to the empty
130131
// string on invalid numbers.
131132
const prevValue = useRef(value);
132-
if (prevValue.current !== value && typeof value === "string") {
133-
prevValue.current = value;
134-
setValued(value.length > 0);
135-
}
133+
useEffect(() => {
134+
if (prevValue.current !== value && typeof value === "string") {
135+
prevValue.current = value;
136+
setValued(value.length > 0);
137+
}
138+
}, [value]);
136139

137140
return {
138141
valued,

0 commit comments

Comments
 (0)