Flow strict TextInput (#22250)

Summary:
Related to #22100

Enhance TextInput with callback event types.
This is a first draft and I will need more help on this one. Flow checks are successful now but I am not sure types are accurate though.
Moreover I find my separation approach kind of dirty for callback event types.

- All flow tests succeed.

[GENERAL] [ENHANCEMENT] [TextInput.js] - Flow types
[GENERAL] [ENHANCEMENT] [TextInputExample.android.js] - Fixing Flow types
[GENERAL] [ENHANCEMENT] [TextInputExample.ios.js] - Fixing Flow types
[GENERAL] [ENHANCEMENT] [XHRExampleFetch.js] - Fixing Flow types
Pull Request resolved: https://github.com/facebook/react-native/pull/22250

Reviewed By: TheSavior

Differential Revision: D13104820

Pulled By: RSNara

fbshipit-source-id: 3fbb98d0ec2b62be676f71ae1053933d9c78485e
This commit is contained in:
Thomas BARRAS 2018-11-21 14:31:31 -08:00 committed by Facebook Github Bot
parent 79274979b7
commit 35a65cd704
4 changed files with 92 additions and 30 deletions

View File

@ -34,6 +34,8 @@ const warning = require('fbjs/lib/warning');
import type {TextStyleProp, ViewStyleProp} from 'StyleSheet';
import type {ColorValue} from 'StyleSheetTypes';
import type {ViewProps} from 'ViewPropTypes';
import type {SyntheticEvent} from 'CoreEventTypes';
import type {PressEvent} from 'CoreEventTypes';
let AndroidTextInput;
let RCTMultilineTextInputView;
@ -55,11 +57,70 @@ const onlyMultiline = {
children: true,
};
type Event = Object;
type Selection = {
type Range = $ReadOnly<{|
start: number,
end: number,
|}>;
type Selection = $ReadOnly<{|
start: number,
end?: number,
};
|}>;
type ContentSize = $ReadOnly<{|
width: number,
height: number,
|}>;
type ContentOffset = $ReadOnly<{|
x: number,
y: number,
|}>;
type ChangeEvent = SyntheticEvent<
$ReadOnly<{|
target: number,
eventCount: number,
text: string,
|}>,
>;
type TextInputEvent = SyntheticEvent<
$ReadOnly<{|
previousText: string,
range: Range,
target: number,
text: string,
|}>,
>;
type ContentSizeChangeEvent = SyntheticEvent<
$ReadOnly<{|
target: number,
contentSize: ContentSize,
|}>,
>;
type ScrollEvent = SyntheticEvent<
$ReadOnly<{|
target: number,
contentOffset: ContentOffset,
|}>,
>;
type TargetEvent = SyntheticEvent<
$ReadOnly<{|
target: number,
|}>,
>;
type SelectionChangeEvent = SyntheticEvent<
$ReadOnly<{|
selection: Selection,
|}>,
>;
type KeyPressEvent = SyntheticEvent<
$ReadOnly<{|
key: string,
|}>,
>;
type EditingEvent = SyntheticEvent<
$ReadOnly<{|
text: string,
target: number,
|}>,
>;
const DataDetectorTypes = [
'phoneNumber',
@ -184,17 +245,17 @@ type Props = $ReadOnly<{|
returnKeyType?: ?ReturnKeyType,
maxLength?: ?number,
multiline?: ?boolean,
onBlur?: ?Function,
onFocus?: ?Function,
onChange?: ?Function,
onChangeText?: ?Function,
onContentSizeChange?: ?Function,
onTextInput?: ?Function,
onEndEditing?: ?Function,
onSelectionChange?: ?Function,
onSubmitEditing?: ?Function,
onKeyPress?: ?Function,
onScroll?: ?Function,
onBlur?: ?(e: TargetEvent) => void,
onFocus?: ?(e: TargetEvent) => void,
onChange?: ?(e: ChangeEvent) => void,
onChangeText?: ?(text: string) => void,
onContentSizeChange?: ?(e: ContentSizeChangeEvent) => void,
onTextInput?: ?(e: TextInputEvent) => void,
onEndEditing?: ?(e: EditingEvent) => void,
onSelectionChange?: ?(e: SelectionChangeEvent) => void,
onSubmitEditing?: ?(e: EditingEvent) => void,
onKeyPress?: ?(e: KeyPressEvent) => void,
onScroll?: ?(e: ScrollEvent) => void,
placeholder?: ?Stringish,
placeholderTextColor?: ?ColorValue,
secureTextEntry?: ?boolean,
@ -792,7 +853,7 @@ const TextInput = createReactClass({
'oneTimeCode',
]),
},
getDefaultProps(): Object {
getDefaultProps() {
return {
allowFontScaling: true,
underlineColorAndroid: 'transparent',
@ -1108,7 +1169,7 @@ const TextInput = createReactClass({
);
},
_onFocus: function(event: Event) {
_onFocus: function(event: TargetEvent) {
if (this.props.onFocus) {
this.props.onFocus(event);
}
@ -1118,13 +1179,13 @@ const TextInput = createReactClass({
}
},
_onPress: function(event: Event) {
_onPress: function(event: PressEvent) {
if (this.props.editable || this.props.editable === undefined) {
this.focus();
}
},
_onChange: function(event: Event) {
_onChange: function(event: ChangeEvent) {
// Make sure to fire the mostRecentEventCount first so it is already set on
// native when the text value is set.
if (this._inputRef && this._inputRef.setNativeProps) {
@ -1147,7 +1208,7 @@ const TextInput = createReactClass({
this.forceUpdate();
},
_onSelectionChange: function(event: Event) {
_onSelectionChange: function(event: SelectionChangeEvent) {
this.props.onSelectionChange && this.props.onSelectionChange(event);
if (!this._inputRef) {
@ -1201,7 +1262,7 @@ const TextInput = createReactClass({
}
},
_onBlur: function(event: Event) {
_onBlur: function(event: TargetEvent) {
if (this.props.onBlur) {
this.props.onBlur(event);
}
@ -1211,11 +1272,11 @@ const TextInput = createReactClass({
}
},
_onTextInput: function(event: Event) {
_onTextInput: function(event: TextInputEvent) {
this.props.onTextInput && this.props.onTextInput(event);
},
_onScroll: function(event: Event) {
_onScroll: function(event: ScrollEvent) {
this.props.onScroll && this.props.onScroll(event);
},
});

View File

@ -48,7 +48,8 @@ class TextEventsExample extends React.Component<{}, $FlowFixMeState> {
}
onContentSizeChange={event =>
this.updateText(
'onContentSizeChange size: ' + event.nativeEvent.contentSize,
'onContentSizeChange size: ' +
JSON.stringify(event.nativeEvent.contentSize),
)
}
onEndEditing={event =>
@ -253,10 +254,10 @@ class ToggleDefaultPaddingExample extends React.Component<
}
type SelectionExampleState = {
selection: {
selection: $ReadOnly<{|
start: number,
end: number,
},
end?: number,
|}>,
value: string,
};

View File

@ -71,7 +71,7 @@ class TextEventsExample extends React.Component<{}, $FlowFixMeState> {
'onSelectionChange range: ' +
event.nativeEvent.selection.start +
',' +
event.nativeEvent.selection.end,
(event.nativeEvent.selection.end || ''),
)
}
onKeyPress={event => {
@ -348,10 +348,10 @@ class BlurOnSubmitExample extends React.Component<{}> {
}
type SelectionExampleState = {
selection: {|
selection: $ReadOnly<{|
start: number,
end?: number,
|},
|}>,
value: string,
};

View File

@ -27,7 +27,7 @@ class XHRExampleFetch extends React.Component<any, any> {
this.responseHeaders = null;
}
submit(uri: String) {
submit(uri: string) {
fetch(uri)
.then(response => {
this.responseURL = response.url;