Skip to content

Commit 8a22aab

Browse files
authored
Infra/ Incubator.WheelPicker selectedValue (#1782)
* deprecate Incubator.WheelPicker selectedValue in favor of initialValue * formatting * update screen * remove redundant const
1 parent 25765fc commit 8a22aab

File tree

6 files changed

+60
-135
lines changed

6 files changed

+60
-135
lines changed

demo/src/screens/incubatorScreens/WheelPickerScreen.tsx

Lines changed: 19 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ import React, {useCallback, useState} from 'react';
22
import {View, Text, Incubator, Colors, Typography, Button, Dialog} from 'react-native-ui-lib';
33
import _ from 'lodash';
44

5-
type WheelPickerValue = Incubator.WheelPickerProps['initialValue'];
6-
75
const monthItems = _.map([
86
'January',
97
'February',
@@ -20,16 +18,19 @@ const monthItems = _.map([
2018
],
2119
item => ({label: item, value: item}));
2220

23-
const yearItems = _.times(2030, i => i)
21+
const yearItems = _.times(2050, i => i)
2422
.reverse()
2523
.map(item => ({label: `${item}`, value: item}));
2624
const dayItems = _.times(31, i => i + 1).map(day => ({label: `${day}`, value: day}));
2725

28-
const useData = (initialMonth?: string, initialYear?: string, initialDays?: number) => {
29-
const [selectedMonth, setMonth] = useState<WheelPickerValue>(initialMonth);
30-
const [, setYear] = useState<WheelPickerValue>(initialYear);
31-
const [selectedDays, setDays] = useState<WheelPickerValue>(initialDays);
26+
export default () => {
3227
const [showDialog, setShowDialog] = useState(false);
28+
const [yearsValue, setYearsValue] = useState(2022);
29+
30+
const updateYearsInitialValue = useCallback((increaseYears: boolean) => {
31+
increaseYears ? setYearsValue(Math.min(yearsValue + 5, 2049)) : setYearsValue(Math.max(yearsValue - 5, 0));
32+
},
33+
[yearsValue]);
3334

3435
const onPickDaysPress = useCallback(() => {
3536
setShowDialog(true);
@@ -39,75 +40,38 @@ const useData = (initialMonth?: string, initialYear?: string, initialDays?: numb
3940
setShowDialog(false);
4041
}, []);
4142

42-
const onMonthChange = useCallback((item: WheelPickerValue, _: number) => {
43-
setMonth(item);
44-
}, []);
45-
46-
const onYearChange = useCallback((item: WheelPickerValue, _: number) => {
47-
setYear(item);
48-
}, []);
49-
50-
const onDaysChange = useCallback((item: WheelPickerValue, _: number) => {
51-
setDays(item);
52-
}, []);
53-
54-
return {
55-
onMonthChange,
56-
onYearChange,
57-
onDaysChange,
58-
selectedMonth,
59-
selectedDays,
60-
onPickDaysPress,
61-
onDialogDismissed,
62-
showDialog
63-
};
64-
};
65-
66-
export default () => {
67-
const {
68-
selectedMonth,
69-
onMonthChange,
70-
onYearChange,
71-
selectedDays,
72-
onDaysChange,
73-
onPickDaysPress,
74-
onDialogDismissed,
75-
showDialog
76-
} = useData('February', undefined, 5);
77-
7843
return (
7944
<View flex padding-page>
8045
<Text h1>Wheel Picker</Text>
8146

8247
<View marginT-s5 centerH>
8348
<Text h3>Months</Text>
8449
<Incubator.WheelPicker
85-
onChange={onMonthChange}
50+
initialValue={'February'}
8651
activeTextColor={Colors.primary}
8752
inactiveTextColor={Colors.grey20}
8853
items={monthItems}
8954
textStyle={Typography.text60R}
90-
selectedValue={selectedMonth}
9155
/>
9256

9357
<Text h3>Years</Text>
94-
<Text bodySmall grey30>
95-
(Uncontrolled, initialValue passed)
96-
</Text>
9758
<View width={'100%'} marginT-s3>
98-
<Incubator.WheelPicker
99-
onChange={onYearChange}
100-
numberOfVisibleRows={3}
101-
initialValue={2021}
102-
items={yearItems}
103-
/>
59+
<Incubator.WheelPicker numberOfVisibleRows={3} initialValue={yearsValue} items={yearItems}/>
60+
</View>
61+
62+
<Text marginT-10 bodySmall grey30>
63+
(update value by passing a new initialValue)
64+
</Text>
65+
<View marginT-10 row>
66+
<Button label={'-5 years'} marginR-20 onPress={() => updateYearsInitialValue(false)}/>
67+
<Button label={'+5 years'} onPress={() => updateYearsInitialValue(true)}/>
10468
</View>
10569
</View>
10670

10771
<View marginB-s10>
10872
<Button marginT-40 label={'Pick Days'} marginH-100 onPress={onPickDaysPress}/>
10973
<Dialog width={'90%'} height={260} bottom visible={showDialog} onDismiss={onDialogDismissed}>
110-
<Incubator.WheelPicker onChange={onDaysChange} selectedValue={selectedDays} label={'Days'} items={dayItems}/>
74+
<Incubator.WheelPicker initialValue={5} label={'Days'} items={dayItems}/>
11175
</Dialog>
11276
</View>
11377
</View>

generatedTypes/src/incubator/WheelPicker/index.d.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,9 @@ export declare enum WheelPickerAlign {
99
}
1010
export interface WheelPickerProps {
1111
/**
12-
* Initial value (doesn't work with selectedValue)
12+
* Initial value
1313
*/
1414
initialValue?: ItemProps | number | string;
15-
/**
16-
* The current selected value
17-
*/
18-
selectedValue?: ItemProps | number | string;
1915
/**
2016
* Data source for WheelPicker
2117
*/
@@ -75,7 +71,7 @@ export interface WheelPickerProps {
7571
declare const _default: React.ComponentClass<WheelPickerProps & {
7672
useCustomTheme?: boolean | undefined;
7773
}, any> & {
78-
({ items: propItems, itemHeight, numberOfVisibleRows, activeTextColor, inactiveTextColor, textStyle, label, labelStyle, labelProps, onChange, align, style, children, initialValue, selectedValue, testID }: WheelPickerProps): JSX.Element;
74+
({ items: propItems, itemHeight, numberOfVisibleRows, activeTextColor, inactiveTextColor, textStyle, label, labelStyle, labelProps, onChange, align, style, children, initialValue, testID }: WheelPickerProps): JSX.Element;
7975
alignments: typeof WheelPickerAlign;
8076
displayName: string;
8177
};

generatedTypes/src/incubator/WheelPicker/usePresenter.d.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { ItemProps } from './Item';
33
export declare type ItemValueTypes = ItemProps | number | string;
44
declare type PropTypes = {
55
initialValue?: ItemValueTypes;
6-
selectedValue?: ItemValueTypes;
76
children?: JSX.Element | JSX.Element[];
87
items?: ItemProps[];
98
itemHeight: number;
@@ -15,10 +14,9 @@ declare type RowItem = {
1514
};
1615
interface Presenter {
1716
items: ItemProps[];
18-
shouldControlComponent: (offset: number) => boolean;
1917
index: number;
2018
height: number;
2119
getRowItemAtOffset: (offset: number) => RowItem;
2220
}
23-
declare const usePresenter: ({ initialValue, selectedValue, children, items: propItems, itemHeight, preferredNumVisibleRows }: PropTypes) => Presenter;
21+
declare const usePresenter: ({ initialValue, children, items: propItems, itemHeight, preferredNumVisibleRows }: PropTypes) => Presenter;
2422
export default usePresenter;

src/incubator/WheelPicker/__tests__/usePresenter.spec.js

Lines changed: 20 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,12 @@ import usePresenter from '../usePresenter';
22
import {renderHook} from '@testing-library/react-hooks';
33

44
describe('WheelPicker presenter tests', () => {
5-
6-
const makeSUT = ({selectedValue, items = makeItems(9), children, itemHeight = 10, preferredNumVisibleRows = 20}) => {
5+
const makeSUT = ({items = makeItems(9), children, initialValue, itemHeight = 10, preferredNumVisibleRows = 20}) => {
76
return renderHook(() =>
87
usePresenter({
9-
selectedValue,
108
items,
119
children,
10+
initialValue,
1211
itemHeight,
1312
preferredNumVisibleRows
1413
}));
@@ -17,7 +16,7 @@ describe('WheelPicker presenter tests', () => {
1716
const makeItems = (count, stringValue) => {
1817
const items = [];
1918
while (count >= items.length) {
20-
const someData = stringValue ? (stringValue + items.length) : items.length;
19+
const someData = stringValue ? stringValue + items.length : items.length;
2120
const item = {value: someData, label: someData};
2221
items.push(item);
2322
}
@@ -27,68 +26,58 @@ describe('WheelPicker presenter tests', () => {
2726
it('expect height of the content-view to be itemHeight * preferredNumVisibleRows', () => {
2827
let sut = makeSUT({items: makeItems(44), itemHeight: 10, preferredNumVisibleRows: 5});
2928
expect(sut.result.current.height).toEqual(50);
30-
29+
3130
sut = makeSUT({items: makeItems(10), itemHeight: 20, preferredNumVisibleRows: 3});
3231
expect(sut.result.current.height).toEqual(60);
33-
32+
3433
sut = makeSUT({items: makeItems(10), itemHeight: 0, preferredNumVisibleRows: 0});
3534
expect(sut.result.current.height).toEqual(0);
3635
});
3736

3837
it('Expect to find items by their string types', () => {
39-
let sut = makeSUT({items: makeItems(15, 'a'), selectedValue: 'a2'});
38+
let sut = makeSUT({items: makeItems(15, 'a'), initialValue: 'a2'});
4039
expect(sut.result.current.index).toEqual(2);
4140

42-
sut = makeSUT({items: makeItems(100, 'bbb'), selectedValue: 'bbb71'});
41+
sut = makeSUT({items: makeItems(100, 'bbb'), initialValue: 'bbb71'});
4342
expect(sut.result.current.index).toEqual(71);
4443

4544
// no data found
46-
sut = makeSUT({items: makeItems(10, 'b'), selectedValue: '$$$'});
45+
sut = makeSUT({items: makeItems(10, 'b'), initialValue: '$$$'});
4746
expect(sut.result.current.index).toEqual(-1);
4847
});
4948

5049
it('Expect to find items by their number types', () => {
51-
let sut = makeSUT({items: makeItems(11), selectedValue: 0});
50+
let sut = makeSUT({items: makeItems(11), initialValue: 0});
5251
expect(sut.result.current.index).toEqual(0);
5352

54-
sut = makeSUT({items: makeItems(8), selectedValue: 4});
53+
sut = makeSUT({items: makeItems(8), initialValue: 4});
5554
expect(sut.result.current.index).toEqual(4);
5655

57-
sut = makeSUT({items: makeItems(18), selectedValue: 18});
56+
sut = makeSUT({items: makeItems(18), initialValue: 18});
5857
expect(sut.result.current.index).toEqual(18);
59-
60-
sut = makeSUT({items: makeItems(18), selectedValue: 99});
58+
59+
sut = makeSUT({items: makeItems(18), initialValue: 99});
6160
expect(sut.result.current.index).toEqual(-1);
6261

63-
sut = makeSUT({items: makeItems(0), selectedValue: 99});
62+
sut = makeSUT({items: makeItems(0), initialValue: 99});
6463
expect(sut.result.current.index).toEqual(-1);
65-
66-
sut = makeSUT({items: makeItems(0), selectedValue: 0});
64+
65+
sut = makeSUT({items: makeItems(0), initialValue: 0});
6766
expect(sut.result.current.index).toEqual(0);
6867
});
6968

7069
it('Expect to find items by their object of {value, label} types', () => {
71-
const {result} = makeSUT({items: makeItems(15, 'b'), selectedValue: {value: 'b6', label: 'abc'}});
70+
const {result} = makeSUT({items: makeItems(15, 'b'), initialValue: {value: 'b6', label: 'abc'}});
7271
expect(result.current.index).toEqual(6);
7372
});
7473

75-
it('Expect component to be controlled and not change by offset', () => {
76-
const {result} = makeSUT({selectedValue: 2, itemHeight: 100});
77-
78-
let offset = 300;
79-
expect(result.current.shouldControlComponent(offset)).toEqual(true);
80-
81-
offset = 200;
82-
expect(result.current.shouldControlComponent(offset)).toEqual(false);
83-
});
84-
8574
it('Expect getRowItemAtOffset to return the right row for offset', () => {
86-
let sut = makeSUT({selectedValue: 2, itemHeight: 100});
87-
75+
let sut = makeSUT({initialValue: 2, itemHeight: 100});
76+
8877
let offset = 300;
8978
expect(sut.result.current.getRowItemAtOffset(offset).value).toEqual(3);
9079

91-
sut = makeSUT({selectedValue: 0, itemHeight: 100});
80+
sut = makeSUT({initialValue: 0, itemHeight: 100});
9281
offset = 0;
9382
expect(sut.result.current.getRowItemAtOffset(offset).value).toEqual(0);
9483
});

src/incubator/WheelPicker/index.tsx

Lines changed: 14 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,9 @@ export enum WheelPickerAlign {
2121

2222
export interface WheelPickerProps {
2323
/**
24-
* Initial value (doesn't work with selectedValue)
24+
* Initial value
2525
*/
2626
initialValue?: ItemProps | number | string;
27-
/**
28-
* The current selected value
29-
*/
30-
selectedValue?: ItemProps | number | string;
3127
/**
3228
* Data source for WheelPicker
3329
*/
@@ -99,8 +95,7 @@ const WheelPicker = ({
9995
align = WheelPickerAlign.CENTER,
10096
style,
10197
children,
102-
initialValue,
103-
selectedValue,
98+
initialValue = 0,
10499
testID
105100
}: WheelPickerProps) => {
106101
const scrollView = useRef<Animated.ScrollView>();
@@ -112,12 +107,10 @@ const WheelPicker = ({
112107
const {
113108
height,
114109
items,
115-
shouldControlComponent,
116110
index: currentIndex,
117111
getRowItemAtOffset
118112
} = usePresenter({
119113
initialValue,
120-
selectedValue,
121114
items: propItems,
122115
children,
123116
itemHeight,
@@ -126,17 +119,9 @@ const WheelPicker = ({
126119

127120
const prevInitialValue = useRef(initialValue);
128121
const prevIndex = useRef(currentIndex);
129-
const [scrollOffset, setScrollOffset] = useState(currentIndex * itemHeight);
130122
const [flatListWidth, setFlatListWidth] = useState(0);
131123
const keyExtractor = useCallback((item: ItemProps, index: number) => `${item}.${index}`, []);
132124

133-
useEffect(() => {
134-
// This effect enforce the index to be controlled by selectedValue passed by the user
135-
if (shouldControlComponent(scrollOffset)) {
136-
scrollToIndex(currentIndex, true);
137-
}
138-
});
139-
140125
useEffect(() => {
141126
// This effect making sure to reset index if initialValue has changed
142127
!isUndefined(initialValue) && scrollToIndex(currentIndex, true);
@@ -149,13 +134,14 @@ const WheelPicker = ({
149134
} else {
150135
onChange?.(value, index);
151136
}
152-
}, [initialValue, onChange]);
137+
},
138+
[initialValue, onChange]);
153139

154140
const onValueChange = useCallback((event: NativeSyntheticEvent<NativeScrollEvent>) => {
155-
setScrollOffset(event.nativeEvent.contentOffset.y);
156141
const {index, value} = getRowItemAtOffset(event.nativeEvent.contentOffset.y);
157142
_onChange(value, index);
158-
}, [_onChange, getRowItemAtOffset]);
143+
},
144+
[_onChange, getRowItemAtOffset]);
159145

160146
const onMomentumScrollEndAndroid = (index: number) => {
161147
// handle Android bug: ScrollView does not call 'onMomentumScrollEnd' when scrolled programmatically (https://github.com/facebook/react-native/issues/26661)
@@ -188,7 +174,8 @@ const WheelPicker = ({
188174

189175
const selectItem = useCallback(index => {
190176
scrollToIndex(index, true);
191-
}, [itemHeight]);
177+
},
178+
[itemHeight]);
192179

193180
const renderItem = useCallback(({item, index}) => {
194181
return (
@@ -208,11 +195,13 @@ const WheelPicker = ({
208195
testID={`${testID}.item_${index}`}
209196
/>
210197
);
211-
}, [itemHeight]);
198+
},
199+
[itemHeight]);
212200

213201
const getItemLayout = useCallback((_data, index: number) => {
214202
return {length: itemHeight, offset: itemHeight * index, index};
215-
}, [itemHeight]);
203+
},
204+
[itemHeight]);
216205

217206
const updateFlatListWidth = useCallback((width: number) => {
218207
setFlatListWidth(width);
@@ -254,7 +243,8 @@ const WheelPicker = ({
254243

255244
const fader = useMemo(() => (position: FaderPosition) => {
256245
return <Fader visible position={position} size={60}/>;
257-
}, []);
246+
},
247+
[]);
258248

259249
const separators = useMemo(() => {
260250
return (

0 commit comments

Comments
 (0)