Skip to content

Commit 9584099

Browse files
authored
Merge branch 'master' into youssef/p-3482-replace-jigsaws-web-maps-implementation
2 parents ba9268c + dd35084 commit 9584099

File tree

5 files changed

+112
-77
lines changed

5 files changed

+112
-77
lines changed

packages/core/src/components/DeckSwiper/DeckSwiper.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ const DeckSwiper = <T extends object>({
5353
);
5454
}
5555

56+
const deckSwiperRef = React.useRef<DeckSwiperComponent<T>>(null);
57+
5658
const childrenArray = React.useMemo(
5759
() => React.Children.toArray(children),
5860
[children]
@@ -89,6 +91,14 @@ const DeckSwiper = <T extends object>({
8991
}
9092
};
9193

94+
/*
95+
react-native-deck-swiper does not re-render cards when parent state changes
96+
This forces an update on every re-render to reflect any parent state changes
97+
*/
98+
React.useEffect(() => {
99+
deckSwiperRef.current?.forceUpdate();
100+
});
101+
92102
/**
93103
* By default react-native-deck-swiper positions everything with absolute position.
94104
* To overcome this, it is wrapped in a View to be able to add the component in any layout structure.
@@ -103,6 +113,7 @@ const DeckSwiper = <T extends object>({
103113
<View>
104114
<View style={styles.containerHeightFiller}>{renderFirstCard()}</View>
105115
<DeckSwiperComponent
116+
ref={deckSwiperRef}
106117
cards={cardsData as any[]}
107118
renderCard={renderCard}
108119
keyExtractor={cardKeyExtractor}
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/components/Swiper/Swiper.tsx

Lines changed: 42 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,16 @@ const Swiper = ({
4040
data,
4141
keyExtractor,
4242
renderItem,
43-
children,
43+
children: childrenProp,
4444
onIndexChanged: onIndexChangedProp,
4545
onSwipe,
4646
onSwipedNext,
4747
onSwipedPrevious,
4848
style,
4949
}: SwiperProps<any>) => {
5050
const [currentIndex, setCurrentIndex] = React.useState(0);
51-
const numberOfItems = data?.length ?? React.Children.count(children);
51+
const numberOfItems = data?.length ?? React.Children.count(childrenProp);
52+
const swiperRef = React.useRef<any>(null);
5253

5354
const onIndexChanged = (index: number) => {
5455
const previous = currentIndex;
@@ -71,10 +72,48 @@ const Swiper = ({
7172
onSwipe?.(previous);
7273
};
7374

75+
const children: React.ReactNode = React.useMemo(
76+
() =>
77+
data && renderItem
78+
? data.map((item, index) => {
79+
const component = renderItem({ item, index });
80+
81+
if (!component) {
82+
return null;
83+
}
84+
85+
const key = keyExtractor ? keyExtractor(item, index) : index;
86+
return React.cloneElement(component, {
87+
key,
88+
});
89+
})
90+
: childrenProp,
91+
[childrenProp, data, renderItem, keyExtractor]
92+
);
93+
94+
/*
95+
react-native-web-swiper assigns it's 'children' attribute as follows: `children = (() => React.Children.toArray(this.props.children))();`
96+
This is probelematic when state is involved due to anoynmous function effectivley creating new components everytime, losing any state
97+
98+
This is a monkey patch that updates the 'children' attribute to just use the children from the props
99+
Can be removed when/if https://github.com/reactrondev/react-native-web-swiper/pull/102 is merged
100+
*/
101+
React.useEffect(() => {
102+
const childrenArray = React.Children.toArray(
103+
swiperRef.current?.props?.children
104+
);
105+
if (swiperRef.current) {
106+
swiperRef.current.children = childrenArray;
107+
swiperRef.current.count = childrenArray.length;
108+
swiperRef.current.forceUpdate();
109+
}
110+
}, [children]);
111+
74112
return (
75113
<View style={style}>
76114
{/* @ts-ignore */}
77115
<SwiperComponent
116+
ref={swiperRef}
78117
from={from}
79118
loop={loop}
80119
timeout={timeout}
@@ -94,20 +133,7 @@ const Swiper = ({
94133
: {}),
95134
}}
96135
>
97-
{data && renderItem
98-
? data.map((item, index) => {
99-
const component = renderItem({ item, index });
100-
101-
if (!component) {
102-
return null;
103-
}
104-
105-
const key = keyExtractor ? keyExtractor(item, index) : index;
106-
return React.cloneElement(component, {
107-
key,
108-
});
109-
})
110-
: children}
136+
{children}
111137
</SwiperComponent>
112138
</View>
113139
);

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)