mirror of
https://github.com/status-im/react-native.git
synced 2025-02-15 10:57:00 +00:00
Summary: Fixing an issue where PickerIOS and DatePicker are being accessed unsafely, As a side effect we are also using ref callbacks as oppose to strings. Fixed after spotting an issue in our app where the picker is closed and the callback attempts to update native props for an item that no longer exists. Closes https://github.com/facebook/react-native/pull/3920 Reviewed By: svcscm Differential Revision: D2663634 Pulled By: nicklockwood fb-gh-sync-id: 813b32a038f59864401d5d3985c7ea32f5e13301
120 lines
3.4 KiB
JavaScript
120 lines
3.4 KiB
JavaScript
/**
|
|
* Copyright (c) 2015-present, Facebook, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* This source code is licensed under the BSD-style license found in the
|
|
* LICENSE file in the root directory of this source tree. An additional grant
|
|
* of patent rights can be found in the PATENTS file in the same directory.
|
|
*
|
|
* @providesModule PickerIOS
|
|
*
|
|
* This is a controlled component version of RCTPickerIOS
|
|
*/
|
|
'use strict';
|
|
|
|
var NativeMethodsMixin = require('NativeMethodsMixin');
|
|
var React = require('React');
|
|
var ReactChildren = require('ReactChildren');
|
|
var RCTPickerIOSConsts = require('NativeModules').UIManager.RCTPicker.Constants;
|
|
var StyleSheet = require('StyleSheet');
|
|
var View = require('View');
|
|
|
|
var requireNativeComponent = require('requireNativeComponent');
|
|
|
|
var PickerIOS = React.createClass({
|
|
mixins: [NativeMethodsMixin],
|
|
|
|
propTypes: {
|
|
...View.propTypes,
|
|
onValueChange: React.PropTypes.func,
|
|
selectedValue: React.PropTypes.any, // string or integer basically
|
|
},
|
|
|
|
getInitialState: function() {
|
|
return this._stateFromProps(this.props);
|
|
},
|
|
|
|
componentWillReceiveProps: function(nextProps) {
|
|
this.setState(this._stateFromProps(nextProps));
|
|
},
|
|
|
|
// Translate PickerIOS prop and children into stuff that RCTPickerIOS understands.
|
|
_stateFromProps: function(props) {
|
|
var selectedIndex = 0;
|
|
var items = [];
|
|
ReactChildren.forEach(props.children, function (child, index) {
|
|
if (child.props.value === props.selectedValue) {
|
|
selectedIndex = index;
|
|
}
|
|
items.push({value: child.props.value, label: child.props.label});
|
|
});
|
|
return {selectedIndex, items};
|
|
},
|
|
|
|
render: function() {
|
|
return (
|
|
<View style={this.props.style}>
|
|
<RCTPickerIOS
|
|
ref={ picker => this._picker = picker }
|
|
style={styles.pickerIOS}
|
|
items={this.state.items}
|
|
selectedIndex={this.state.selectedIndex}
|
|
onChange={this._onChange}
|
|
/>
|
|
</View>
|
|
);
|
|
},
|
|
|
|
_onChange: function(event) {
|
|
if (this.props.onChange) {
|
|
this.props.onChange(event);
|
|
}
|
|
if (this.props.onValueChange) {
|
|
this.props.onValueChange(event.nativeEvent.newValue);
|
|
}
|
|
|
|
// The picker is a controlled component. This means we expect the
|
|
// on*Change handlers to be in charge of updating our
|
|
// `selectedValue` prop. That way they can also
|
|
// disallow/undo/mutate the selection of certain values. In other
|
|
// words, the embedder of this component should be the source of
|
|
// truth, not the native component.
|
|
if (this._picker && this.state.selectedIndex !== event.nativeEvent.newIndex) {
|
|
this._picker.setNativeProps({
|
|
selectedIndex: this.state.selectedIndex
|
|
});
|
|
}
|
|
},
|
|
});
|
|
|
|
PickerIOS.Item = React.createClass({
|
|
propTypes: {
|
|
value: React.PropTypes.any, // string or integer basically
|
|
label: React.PropTypes.string,
|
|
},
|
|
|
|
render: function() {
|
|
// These items don't get rendered directly.
|
|
return null;
|
|
},
|
|
});
|
|
|
|
var styles = StyleSheet.create({
|
|
pickerIOS: {
|
|
// The picker will conform to whatever width is given, but we do
|
|
// have to set the component's height explicitly on the
|
|
// surrounding view to ensure it gets rendered.
|
|
height: RCTPickerIOSConsts.ComponentHeight,
|
|
},
|
|
});
|
|
|
|
var RCTPickerIOS = requireNativeComponent('RCTPicker', PickerIOS, {
|
|
nativeOnly: {
|
|
items: true,
|
|
onChange: true,
|
|
selectedIndex: true,
|
|
},
|
|
});
|
|
|
|
module.exports = PickerIOS;
|