RN: Replace `context.isInAParentText` w/ React.createContext
Reviewed By: sahrens Differential Revision: D7895382 fbshipit-source-id: 4affcecd147b8e8c506e0d94f223bac3e6dfdf66
This commit is contained in:
parent
5d4c542c58
commit
e1339bc183
|
@ -20,6 +20,7 @@ const PropTypes = require('prop-types');
|
|||
const ReactNative = require('ReactNative');
|
||||
const StyleSheet = require('StyleSheet');
|
||||
const Text = require('Text');
|
||||
const TextAncestor = require('TextAncestor');
|
||||
const TextInputState = require('TextInputState');
|
||||
/* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an error
|
||||
* found when Flow v0.54 was deployed. To see the error delete this comment and
|
||||
|
@ -28,7 +29,6 @@ const TimerMixin = require('react-timer-mixin');
|
|||
const TouchableWithoutFeedback = require('TouchableWithoutFeedback');
|
||||
const UIManager = require('UIManager');
|
||||
const ViewPropTypes = require('ViewPropTypes');
|
||||
const {ViewContextTypes} = require('ViewContext');
|
||||
|
||||
const emptyFunction = require('fbjs/lib/emptyFunction');
|
||||
const invariant = require('fbjs/lib/invariant');
|
||||
|
@ -47,8 +47,6 @@ const onlyMultiline = {
|
|||
children: true,
|
||||
};
|
||||
|
||||
import type {ViewChildContext} from 'ViewContext';
|
||||
|
||||
if (Platform.OS === 'android') {
|
||||
AndroidTextInput = requireNativeComponent('AndroidTextInput', null);
|
||||
} else if (Platform.OS === 'ios') {
|
||||
|
@ -701,16 +699,7 @@ const TextInput = createReactClass({
|
|||
}
|
||||
},
|
||||
|
||||
getChildContext(): ViewChildContext {
|
||||
return {
|
||||
isInAParentText: true,
|
||||
};
|
||||
},
|
||||
|
||||
childContextTypes: ViewContextTypes,
|
||||
|
||||
contextTypes: {
|
||||
...ViewContextTypes,
|
||||
onFocusRequested: PropTypes.func,
|
||||
focusEmitter: PropTypes.instanceOf(EventEmitter),
|
||||
},
|
||||
|
@ -723,13 +712,17 @@ const TextInput = createReactClass({
|
|||
},
|
||||
|
||||
render: function() {
|
||||
let textInput;
|
||||
if (Platform.OS === 'ios') {
|
||||
return UIManager.RCTVirtualText
|
||||
textInput = UIManager.RCTVirtualText
|
||||
? this._renderIOS()
|
||||
: this._renderIOSLegacy();
|
||||
} else if (Platform.OS === 'android') {
|
||||
return this._renderAndroid();
|
||||
textInput = this._renderAndroid();
|
||||
}
|
||||
return (
|
||||
<TextAncestor.Provider value={true}>{textInput}</TextAncestor.Provider>
|
||||
);
|
||||
},
|
||||
|
||||
_getText: function(): ?string {
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
* @flow
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const Platform = require('Platform');
|
||||
|
@ -14,13 +15,13 @@ const React = require('React');
|
|||
const ReactNative = require('ReactNative');
|
||||
const ReactNativeStyleAttributes = require('ReactNativeStyleAttributes');
|
||||
const ReactNativeViewAttributes = require('ReactNativeViewAttributes');
|
||||
const TextAncestor = require('TextAncestor');
|
||||
const ViewPropTypes = require('ViewPropTypes');
|
||||
const {ViewContextTypes} = require('ViewContext');
|
||||
|
||||
const invariant = require('fbjs/lib/invariant');
|
||||
const requireNativeComponent = require('requireNativeComponent');
|
||||
|
||||
import type {ViewProps} from 'ViewPropTypes';
|
||||
import type {ViewChildContext} from 'ViewContext';
|
||||
|
||||
export type Props = ViewProps;
|
||||
|
||||
|
@ -33,30 +34,31 @@ export type Props = ViewProps;
|
|||
*/
|
||||
class View extends ReactNative.NativeComponent<Props> {
|
||||
static propTypes = ViewPropTypes;
|
||||
static childContextTypes = ViewContextTypes;
|
||||
|
||||
viewConfig = {
|
||||
uiViewClassName: 'RCTView',
|
||||
validAttributes: ReactNativeViewAttributes.RCTView,
|
||||
};
|
||||
|
||||
getChildContext(): ViewChildContext {
|
||||
return {
|
||||
isInAParentText: false,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* WARNING: This method will not be used in production mode as in that mode we
|
||||
* replace wrapper component View with generated native wrapper RCTView. Avoid
|
||||
* adding functionality this component that you'd want to be available in both
|
||||
* dev and prod modes.
|
||||
*/
|
||||
render() {
|
||||
invariant(
|
||||
!(this.context.isInAParentText && Platform.OS === 'android'),
|
||||
'Nesting of <View> within <Text> is not supported on Android.',
|
||||
return (
|
||||
<TextAncestor.Consumer>
|
||||
{hasTextAncestor => {
|
||||
// TODO: Change iOS to behave the same as Android.
|
||||
invariant(
|
||||
!hasTextAncestor || Platform.OS !== 'android',
|
||||
'Nesting of <View> within <Text> is not supported on Android.',
|
||||
);
|
||||
return <RCTView {...this.props} />;
|
||||
}}
|
||||
</TextAncestor.Consumer>
|
||||
);
|
||||
|
||||
// WARNING: This method will not be used in production mode as in that mode we
|
||||
// replace wrapper component View with generated native wrapper RCTView. Avoid
|
||||
// adding functionality this component that you'd want to be available in both
|
||||
// dev and prod modes.
|
||||
return <RCTView {...this.props} />;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
* @flow
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var ImageResizeMode = require('ImageResizeMode');
|
||||
|
@ -18,6 +19,7 @@ var PropTypes = require('prop-types');
|
|||
var ReactNativeViewAttributes = require('ReactNativeViewAttributes');
|
||||
var StyleSheet = require('StyleSheet');
|
||||
var StyleSheetPropType = require('StyleSheetPropType');
|
||||
const TextAncestor = require('TextAncestor');
|
||||
var ViewPropTypes = require('ViewPropTypes');
|
||||
|
||||
var createReactClass = require('create-react-class');
|
||||
|
@ -26,8 +28,6 @@ var merge = require('merge');
|
|||
var requireNativeComponent = require('requireNativeComponent');
|
||||
var resolveAssetSource = require('resolveAssetSource');
|
||||
|
||||
const {ViewContextTypes} = require('ViewContext');
|
||||
|
||||
var {ImageLoader} = NativeModules;
|
||||
|
||||
let _requestId = 1;
|
||||
|
@ -202,8 +202,6 @@ var Image = createReactClass({
|
|||
validAttributes: ReactNativeViewAttributes.RCTView,
|
||||
},
|
||||
|
||||
contextTypes: ViewContextTypes,
|
||||
|
||||
render: function() {
|
||||
const source = resolveAssetSource(this.props.source);
|
||||
const defaultSource = resolveAssetSource(this.props.defaultSource);
|
||||
|
@ -236,42 +234,44 @@ var Image = createReactClass({
|
|||
);
|
||||
}
|
||||
|
||||
if (source && (source.uri || Array.isArray(source))) {
|
||||
let style;
|
||||
let sources;
|
||||
if (source.uri) {
|
||||
const {width, height} = source;
|
||||
style = flattenStyle([{width, height}, styles.base, this.props.style]);
|
||||
sources = [{uri: source.uri}];
|
||||
} else {
|
||||
style = flattenStyle([styles.base, this.props.style]);
|
||||
sources = source;
|
||||
}
|
||||
|
||||
const {onLoadStart, onLoad, onLoadEnd, onError} = this.props;
|
||||
const nativeProps = merge(this.props, {
|
||||
style,
|
||||
shouldNotifyLoadEvents: !!(
|
||||
onLoadStart ||
|
||||
onLoad ||
|
||||
onLoadEnd ||
|
||||
onError
|
||||
),
|
||||
src: sources,
|
||||
headers: source.headers,
|
||||
defaultSrc: defaultSource ? defaultSource.uri : null,
|
||||
loadingIndicatorSrc: loadingIndicatorSource
|
||||
? loadingIndicatorSource.uri
|
||||
: null,
|
||||
});
|
||||
|
||||
if (this.context.isInAParentText) {
|
||||
return <RCTTextInlineImage {...nativeProps} />;
|
||||
} else {
|
||||
return <RKImage {...nativeProps} />;
|
||||
}
|
||||
if (!source || (!source.uri && !Array.isArray(source))) {
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
|
||||
let style;
|
||||
let sources;
|
||||
if (source.uri) {
|
||||
const {width, height} = source;
|
||||
style = flattenStyle([{width, height}, styles.base, this.props.style]);
|
||||
sources = [{uri: source.uri}];
|
||||
} else {
|
||||
style = flattenStyle([styles.base, this.props.style]);
|
||||
sources = source;
|
||||
}
|
||||
|
||||
const {onLoadStart, onLoad, onLoadEnd, onError} = this.props;
|
||||
const nativeProps = merge(this.props, {
|
||||
style,
|
||||
shouldNotifyLoadEvents: !!(onLoadStart || onLoad || onLoadEnd || onError),
|
||||
src: sources,
|
||||
headers: source.headers,
|
||||
defaultSrc: defaultSource ? defaultSource.uri : null,
|
||||
loadingIndicatorSrc: loadingIndicatorSource
|
||||
? loadingIndicatorSource.uri
|
||||
: null,
|
||||
});
|
||||
|
||||
return (
|
||||
<TextAncestor.Consumer>
|
||||
{hasTextAncestor =>
|
||||
hasTextAncestor ? (
|
||||
<RCTTextInlineImage {...nativeProps} />
|
||||
) : (
|
||||
<RKImage {...nativeProps} />
|
||||
)
|
||||
}
|
||||
</TextAncestor.Consumer>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
const React = require('React');
|
||||
const ReactNative = require('ReactNative');
|
||||
const ReactNativeViewAttributes = require('ReactNativeViewAttributes');
|
||||
const TextAncestor = require('TextAncestor');
|
||||
const TextPropTypes = require('TextPropTypes');
|
||||
const Touchable = require('Touchable');
|
||||
const UIManager = require('UIManager');
|
||||
|
@ -19,11 +20,9 @@ const UIManager = require('UIManager');
|
|||
const createReactNativeComponentClass = require('createReactNativeComponentClass');
|
||||
const mergeFast = require('mergeFast');
|
||||
const processColor = require('processColor');
|
||||
const {ViewContextTypes} = require('ViewContext');
|
||||
|
||||
import type {PressEvent} from 'CoreEventTypes';
|
||||
import type {TextProps} from 'TextProps';
|
||||
import type {ViewChildContext} from 'ViewContext';
|
||||
|
||||
type State = {
|
||||
isHighlighted: boolean,
|
||||
|
@ -61,8 +60,6 @@ const viewConfig = {
|
|||
*/
|
||||
class Text extends ReactNative.NativeComponent<TextProps, State> {
|
||||
static propTypes = TextPropTypes;
|
||||
static childContextTypes = ViewContextTypes;
|
||||
static contextTypes = ViewContextTypes;
|
||||
|
||||
static defaultProps = {
|
||||
accessible: true,
|
||||
|
@ -76,12 +73,6 @@ class Text extends ReactNative.NativeComponent<TextProps, State> {
|
|||
|
||||
viewConfig = viewConfig;
|
||||
|
||||
getChildContext(): ViewChildContext {
|
||||
return {
|
||||
isInAParentText: true,
|
||||
};
|
||||
}
|
||||
|
||||
_handlers: ?Object;
|
||||
|
||||
_hasPressHandler(): boolean {
|
||||
|
@ -215,11 +206,19 @@ class Text extends ReactNative.NativeComponent<TextProps, State> {
|
|||
style: [this.props.style, {color: 'magenta'}],
|
||||
};
|
||||
}
|
||||
if (this.context.isInAParentText) {
|
||||
return <RCTVirtualText {...newProps} />;
|
||||
} else {
|
||||
return <RCTText {...newProps} />;
|
||||
}
|
||||
return (
|
||||
<TextAncestor.Consumer>
|
||||
{hasTextAncestor =>
|
||||
hasTextAncestor ? (
|
||||
<RCTVirtualText {...newProps} />
|
||||
) : (
|
||||
<TextAncestor.Provider value={true}>
|
||||
<RCTText {...newProps} />
|
||||
</TextAncestor.Provider>
|
||||
)
|
||||
}
|
||||
</TextAncestor.Consumer>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,16 +7,12 @@
|
|||
* @flow
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const PropTypes = require('prop-types');
|
||||
const React = require('React');
|
||||
|
||||
export type ViewChildContext = {|
|
||||
+isInAParentText: boolean,
|
||||
|};
|
||||
|
||||
module.exports = {
|
||||
ViewContextTypes: {
|
||||
isInAParentText: PropTypes.bool,
|
||||
},
|
||||
};
|
||||
/**
|
||||
* Whether the current element is the descendant of a <Text> element.
|
||||
*/
|
||||
module.exports = React.createContext(false);
|
Loading…
Reference in New Issue