3
3
4
4
import _ from 'lodash' ;
5
5
import PropTypes from 'prop-types' ;
6
- import React from 'react' ;
7
- import { BaseComponent } from '../../commons' ;
6
+ import React , { PureComponent } from 'react' ;
7
+ import { asBaseComponent , forwardRef } from '../../commons' ;
8
8
import View from '../../components/view' ;
9
9
import Modal from '../modal' ;
10
10
import Button from '../../components/button' ;
@@ -14,6 +14,7 @@ import NativePicker from './NativePicker';
14
14
import PickerModal from './PickerModal' ;
15
15
import PickerItem from './PickerItem' ;
16
16
17
+
17
18
const PICKER_MODES = {
18
19
SINGLE : 'SINGLE' ,
19
20
MULTI : 'MULTI'
@@ -28,7 +29,7 @@ const ItemType = PropTypes.shape({
28
29
* @gif : https://media.giphy.com/media/3o751SiuZZiByET2lq/giphy.gif, https://media.giphy.com/media/TgMQnyw5grJIDohzvx/giphy.gif, https://media.giphy.com/media/5hsdmVptBRskZKn787/giphy.gif
29
30
* @example : https://github.com/wix/react-native-ui-lib/blob/master/demo/src/screens/componentScreens/PickerScreen.js
30
31
*/
31
- class Picker extends BaseComponent {
32
+ class Picker extends PureComponent {
32
33
static displayName = 'Picker' ;
33
34
static propTypes = {
34
35
...TextField . propTypes ,
@@ -142,6 +143,7 @@ class Picker extends BaseComponent {
142
143
143
144
this . state = {
144
145
value : props . value ,
146
+ prevValue : undefined ,
145
147
selectedItemPosition : 0 ,
146
148
items : this . extractPickerItems ( props )
147
149
} ;
@@ -160,20 +162,30 @@ class Picker extends BaseComponent {
160
162
// }
161
163
}
162
164
163
- UNSAFE_componentWillReceiveProps ( nexProps ) {
164
- this . setState ( {
165
- value : nexProps . value
166
- } ) ;
165
+ static getDerivedStateFromProps ( nextProps , prevState ) {
166
+ if ( ! _ . isEmpty ( nextProps . value ) && prevState . value !== nextProps . value ) {
167
+ if ( prevState . prevValue !== prevState . value ) { // for this.setState() updates to 'value'
168
+ // NOTE: this.setState() already updated the 'value' so here we only updating the 'prevValue'
169
+ return {
170
+ prevValue : prevState . value
171
+ } ;
172
+ } else { // for prop update to 'value'
173
+ return {
174
+ value : nextProps . value
175
+ } ;
176
+ }
177
+ }
178
+ return null ;
167
179
}
168
180
169
181
getAccessibilityInfo ( ) {
170
182
const { placeholder} = this . props ;
183
+
171
184
return {
172
185
accessibilityLabel : this . getLabelValueText ( ) ? `${ placeholder } . selected. ${ this . getLabelValueText ( ) } ` : `Select ${ placeholder } ` ,
173
186
accessibilityHint : this . getLabelValueText ( )
174
187
? 'Double tap to edit'
175
- : `Goes to ${ placeholder } . Suggestions will be provided` ,
176
- ...this . extractAccessibilityProps ( )
188
+ : `Goes to ${ placeholder } . Suggestions will be provided`
177
189
} ;
178
190
}
179
191
@@ -191,6 +203,7 @@ class Picker extends BaseComponent {
191
203
getLabelValueText = ( ) => {
192
204
const { value : propsValue } = this . props ;
193
205
const { value : stateValue } = this . props ;
206
+
194
207
if ( this . shouldNotChangePickerLabelWhileSelecting ( ) ) {
195
208
return this . getLabel ( propsValue ) ;
196
209
}
@@ -223,6 +236,7 @@ class Picker extends BaseComponent {
223
236
// otherwise, extract from picker items
224
237
const { items} = this . state ;
225
238
const selectedItem = _ . find ( items , { value} ) ;
239
+
226
240
return _ . get ( selectedItem , 'label' ) ;
227
241
}
228
242
@@ -240,39 +254,29 @@ class Picker extends BaseComponent {
240
254
const { getItemValue} = this . props ;
241
255
const { value} = this . state ;
242
256
const newValue = _ . xorBy ( value , [ item ] , getItemValue || 'value' ) ;
243
- this . setState ( {
244
- value : newValue
245
- } ) ;
257
+
258
+ this . setState ( { value : newValue } ) ;
246
259
} ;
247
260
248
261
cancelSelect = ( ) => {
249
- this . setState ( {
250
- value : this . props . value
251
- } ) ;
262
+ this . setState ( { value : this . props . value } ) ;
252
263
this . toggleExpandableModal ( false ) ;
253
264
_ . invoke ( this . props , 'topBarProps.onCancel' ) ;
254
265
} ;
255
266
256
267
onDoneSelecting = item => {
257
268
this . clearSearchField ( ) ;
258
-
259
269
this . setState ( { value : item } ) ;
260
270
this . toggleExpandableModal ( false ) ;
261
271
_ . invoke ( this . props , 'onChange' , item ) ;
262
272
} ;
263
273
264
274
onSearchChange = searchValue => {
265
- this . setState ( {
266
- searchValue
267
- } ) ;
275
+ this . setState ( { searchValue} ) ;
268
276
_ . invoke ( this . props , 'onSearchChange' , searchValue ) ;
269
277
} ;
270
278
271
- onSelectedItemLayout = ( {
272
- nativeEvent : {
273
- layout : { y}
274
- }
275
- } ) => {
279
+ onSelectedItemLayout = ( { nativeEvent : { layout : { y} } } ) => {
276
280
this . setState ( { selectedItemPosition : y } ) ;
277
281
} ;
278
282
@@ -290,6 +294,7 @@ class Picker extends BaseComponent {
290
294
if ( ! showSearch || _ . isEmpty ( searchValue ) || _ . includes ( _ . lowerCase ( childLabel ) , _ . lowerCase ( searchValue ) ) ) {
291
295
const selectedValue = PickerPresenter . getItemValue ( { value, getItemValue} ) ;
292
296
const isSelected = PickerPresenter . isItemSelected ( childValue , selectedValue ) ;
297
+
293
298
return React . cloneElement ( child , {
294
299
isSelected,
295
300
onPress : mode === Picker . modes . MULTI ? this . toggleItemSelection : this . onDoneSelecting ,
@@ -318,7 +323,7 @@ class Picker extends BaseComponent {
318
323
renderCustomModal,
319
324
listProps,
320
325
testID
321
- } = this . getThemeProps ( ) ;
326
+ } = this . props ;
322
327
const { showExpandableModal, selectedItemPosition, value} = this . state ;
323
328
const children = this . appendPropsToChildren ( this . props . children ) ;
324
329
@@ -331,6 +336,7 @@ class Picker extends BaseComponent {
331
336
onDone : ( ) => this . onDoneSelecting ( value ) ,
332
337
onCancel : this . cancelSelect
333
338
} ;
339
+
334
340
return renderCustomModal ( modalProps ) ;
335
341
}
336
342
@@ -366,6 +372,7 @@ class Picker extends BaseComponent {
366
372
367
373
if ( _ . isFunction ( renderPicker ) ) {
368
374
const { value} = this . state ;
375
+
369
376
return (
370
377
< View left >
371
378
< Button { ...customPickerProps } link onPress = { this . handlePickerOnPress } testID = { testID } >
@@ -376,8 +383,9 @@ class Picker extends BaseComponent {
376
383
) ;
377
384
}
378
385
379
- const textInputProps = TextField . extractOwnProps ( this . getThemeProps ( ) ) ;
386
+ const textInputProps = TextField . extractOwnProps ( this . props ) ;
380
387
const label = this . getLabelValueText ( ) ;
388
+
381
389
return (
382
390
< TextField
383
391
{ ...textInputProps }
@@ -393,4 +401,6 @@ class Picker extends BaseComponent {
393
401
}
394
402
395
403
Picker . Item = PickerItem ;
396
- export default Picker ;
404
+
405
+ export { Picker } ; // For tests
406
+ export default asBaseComponent ( forwardRef ( Picker ) ) ;
0 commit comments