Skip to content

Commit 79c7071

Browse files
authored
Refs for Input components (#677)
* Forward ref for number input * Forward ref when injecting icon
1 parent 989e40e commit 79c7071

File tree

3 files changed

+59
-61
lines changed

3 files changed

+59
-61
lines changed
Lines changed: 52 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { FC, useEffect, useState } from "react";
1+
import React, { useEffect, useState } from "react";
22
import { TextInput } from "react-native";
33
import { isString, isNumber, isNaN } from "lodash";
44

@@ -8,68 +8,67 @@ interface Props {
88
onChangeText?: (value?: number) => void;
99
}
1010

11-
const NumberInput: FC<Props> = ({
12-
onChangeText,
13-
value,
14-
defaultValue,
15-
...props
16-
}) => {
17-
const [currentStringNumberValue, setCurrentStringNumberValue] = useState("");
11+
const NumberInput = React.forwardRef<TextInput, Props>(
12+
({ onChangeText, value, defaultValue, ...props }, ref) => {
13+
const [currentStringNumberValue, setCurrentStringNumberValue] =
14+
useState("");
1815

19-
const formatValueToStringNumber = (valueToFormat?: number | string) => {
20-
if (valueToFormat != null) {
21-
if (isString(valueToFormat) && valueToFormat !== "") {
22-
if (/^0[1-9]$/.test(valueToFormat)) {
23-
return valueToFormat.slice(1);
24-
} else if (/^[+-]?([0-9]+\.?[0-9]*|\.[0-9]+)$/.test(valueToFormat)) {
25-
return valueToFormat;
26-
} else {
27-
return currentStringNumberValue;
16+
const formatValueToStringNumber = (valueToFormat?: number | string) => {
17+
if (valueToFormat != null) {
18+
if (isString(valueToFormat) && valueToFormat !== "") {
19+
if (/^0[1-9]$/.test(valueToFormat)) {
20+
return valueToFormat.slice(1);
21+
} else if (/^[+-]?([0-9]+\.?[0-9]*|\.[0-9]+)$/.test(valueToFormat)) {
22+
return valueToFormat;
23+
} else {
24+
return currentStringNumberValue;
25+
}
26+
} else if (isNumber(valueToFormat) && !isNaN(valueToFormat)) {
27+
return valueToFormat.toString();
2828
}
29-
} else if (isNumber(valueToFormat) && !isNaN(valueToFormat)) {
30-
return valueToFormat.toString();
3129
}
32-
}
3330

34-
return "";
35-
};
31+
return "";
32+
};
3633

37-
const handleChangeText = (newValue: string) => {
38-
const newStringNumberValue = formatValueToStringNumber(newValue);
39-
const number = parseFloat(newStringNumberValue);
34+
const handleChangeText = (newValue: string) => {
35+
const newStringNumberValue = formatValueToStringNumber(newValue);
36+
const number = parseFloat(newStringNumberValue);
4037

41-
setCurrentStringNumberValue(newStringNumberValue);
42-
onChangeText?.(number);
43-
};
38+
setCurrentStringNumberValue(newStringNumberValue);
39+
onChangeText?.(number);
40+
};
4441

45-
// run handleChangeText with value prop only when value prop changes (and first render to reset currentStringNumberValue)
46-
useEffect(() => {
47-
const nextStringNumberValue = formatValueToStringNumber(value);
42+
// run handleChangeText with value prop only when value prop changes (and first render to reset currentStringNumberValue)
43+
useEffect(() => {
44+
const nextStringNumberValue = formatValueToStringNumber(value);
4845

49-
if (currentStringNumberValue !== nextStringNumberValue) {
50-
handleChangeText(nextStringNumberValue);
51-
}
52-
// eslint-disable-next-line react-hooks/exhaustive-deps
53-
}, [value]);
46+
if (currentStringNumberValue !== nextStringNumberValue) {
47+
handleChangeText(nextStringNumberValue);
48+
}
49+
// eslint-disable-next-line react-hooks/exhaustive-deps
50+
}, [value]);
5451

55-
// set currentStringNumberValue as defaultValue prop if there is a differnce on first render only
56-
useEffect(() => {
57-
const defaultStringNumberValue = formatValueToStringNumber(defaultValue);
52+
// set currentStringNumberValue as defaultValue prop if there is a differnce on first render only
53+
useEffect(() => {
54+
const defaultStringNumberValue = formatValueToStringNumber(defaultValue);
5855

59-
if (currentStringNumberValue !== defaultStringNumberValue) {
60-
setCurrentStringNumberValue(defaultStringNumberValue);
61-
}
62-
// eslint-disable-next-line react-hooks/exhaustive-deps
63-
}, []);
56+
if (currentStringNumberValue !== defaultStringNumberValue) {
57+
setCurrentStringNumberValue(defaultStringNumberValue);
58+
}
59+
// eslint-disable-next-line react-hooks/exhaustive-deps
60+
}, []);
6461

65-
return (
66-
<TextInput
67-
keyboardType="numeric"
68-
value={currentStringNumberValue}
69-
onChangeText={handleChangeText}
70-
{...props}
71-
/>
72-
);
73-
};
62+
return (
63+
<TextInput
64+
ref={ref}
65+
keyboardType="numeric"
66+
value={currentStringNumberValue}
67+
onChangeText={handleChangeText}
68+
{...props}
69+
/>
70+
);
71+
}
72+
);
7473

7574
export default NumberInput;

packages/core/src/interfaces/Icon.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@ export interface IconSlot {
2222

2323
type $Without<T, K> = Pick<T, Exclude<keyof T, K>>;
2424

25-
export const injectIcon =
26-
<P extends IconSlot>(
27-
Component: React.ComponentType<P>,
28-
Icon: IconI
29-
): React.FC<$Without<P, "Icon">> =>
30-
(props) =>
31-
React.createElement(Component, { ...(props as P), Icon });
25+
export const injectIcon = <P extends IconSlot>(
26+
Component: React.ComponentType<P>,
27+
Icon: IconI
28+
) =>
29+
React.forwardRef<any, $Without<P, "Icon">>((props, ref) =>
30+
React.createElement(Component, { ...(props as P), Icon, ref })
31+
);

packages/ui/src/index.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ export {
4242
TableCell,
4343
SwipeableItemButton,
4444
SwipeableList,
45-
/* Deprecated, needs fixing */
4645
ProgressBar,
4746
ProgressCircle,
4847
RowHeadlineImageCaption,

0 commit comments

Comments
 (0)