Skip to content

Commit e1339bc

Browse files
yungstersfacebook-github-bot
authored andcommitted
RN: Replace context.isInAParentText w/ React.createContext
Reviewed By: sahrens Differential Revision: D7895382 fbshipit-source-id: 4affcecd147b8e8c506e0d94f223bac3e6dfdf66
1 parent 5d4c542 commit e1339bc

File tree

5 files changed

+85
-95
lines changed

5 files changed

+85
-95
lines changed

Libraries/Components/TextInput/TextInput.js

+7-14
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ const PropTypes = require('prop-types');
2020
const ReactNative = require('ReactNative');
2121
const StyleSheet = require('StyleSheet');
2222
const Text = require('Text');
23+
const TextAncestor = require('TextAncestor');
2324
const TextInputState = require('TextInputState');
2425
/* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an error
2526
* 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');
2829
const TouchableWithoutFeedback = require('TouchableWithoutFeedback');
2930
const UIManager = require('UIManager');
3031
const ViewPropTypes = require('ViewPropTypes');
31-
const {ViewContextTypes} = require('ViewContext');
3232

3333
const emptyFunction = require('fbjs/lib/emptyFunction');
3434
const invariant = require('fbjs/lib/invariant');
@@ -47,8 +47,6 @@ const onlyMultiline = {
4747
children: true,
4848
};
4949

50-
import type {ViewChildContext} from 'ViewContext';
51-
5250
if (Platform.OS === 'android') {
5351
AndroidTextInput = requireNativeComponent('AndroidTextInput', null);
5452
} else if (Platform.OS === 'ios') {
@@ -701,16 +699,7 @@ const TextInput = createReactClass({
701699
}
702700
},
703701

704-
getChildContext(): ViewChildContext {
705-
return {
706-
isInAParentText: true,
707-
};
708-
},
709-
710-
childContextTypes: ViewContextTypes,
711-
712702
contextTypes: {
713-
...ViewContextTypes,
714703
onFocusRequested: PropTypes.func,
715704
focusEmitter: PropTypes.instanceOf(EventEmitter),
716705
},
@@ -723,13 +712,17 @@ const TextInput = createReactClass({
723712
},
724713

725714
render: function() {
715+
let textInput;
726716
if (Platform.OS === 'ios') {
727-
return UIManager.RCTVirtualText
717+
textInput = UIManager.RCTVirtualText
728718
? this._renderIOS()
729719
: this._renderIOSLegacy();
730720
} else if (Platform.OS === 'android') {
731-
return this._renderAndroid();
721+
textInput = this._renderAndroid();
732722
}
723+
return (
724+
<TextAncestor.Provider value={true}>{textInput}</TextAncestor.Provider>
725+
);
733726
},
734727

735728
_getText: function(): ?string {

Libraries/Components/View/View.js

+20-18
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,21 @@
77
* @flow
88
* @format
99
*/
10+
1011
'use strict';
1112

1213
const Platform = require('Platform');
1314
const React = require('React');
1415
const ReactNative = require('ReactNative');
1516
const ReactNativeStyleAttributes = require('ReactNativeStyleAttributes');
1617
const ReactNativeViewAttributes = require('ReactNativeViewAttributes');
18+
const TextAncestor = require('TextAncestor');
1719
const ViewPropTypes = require('ViewPropTypes');
18-
const {ViewContextTypes} = require('ViewContext');
20+
1921
const invariant = require('fbjs/lib/invariant');
2022
const requireNativeComponent = require('requireNativeComponent');
2123

2224
import type {ViewProps} from 'ViewPropTypes';
23-
import type {ViewChildContext} from 'ViewContext';
2425

2526
export type Props = ViewProps;
2627

@@ -33,30 +34,31 @@ export type Props = ViewProps;
3334
*/
3435
class View extends ReactNative.NativeComponent<Props> {
3536
static propTypes = ViewPropTypes;
36-
static childContextTypes = ViewContextTypes;
3737

3838
viewConfig = {
3939
uiViewClassName: 'RCTView',
4040
validAttributes: ReactNativeViewAttributes.RCTView,
4141
};
4242

43-
getChildContext(): ViewChildContext {
44-
return {
45-
isInAParentText: false,
46-
};
47-
}
48-
43+
/**
44+
* WARNING: This method will not be used in production mode as in that mode we
45+
* replace wrapper component View with generated native wrapper RCTView. Avoid
46+
* adding functionality this component that you'd want to be available in both
47+
* dev and prod modes.
48+
*/
4949
render() {
50-
invariant(
51-
!(this.context.isInAParentText && Platform.OS === 'android'),
52-
'Nesting of <View> within <Text> is not supported on Android.',
50+
return (
51+
<TextAncestor.Consumer>
52+
{hasTextAncestor => {
53+
// TODO: Change iOS to behave the same as Android.
54+
invariant(
55+
!hasTextAncestor || Platform.OS !== 'android',
56+
'Nesting of <View> within <Text> is not supported on Android.',
57+
);
58+
return <RCTView {...this.props} />;
59+
}}
60+
</TextAncestor.Consumer>
5361
);
54-
55-
// WARNING: This method will not be used in production mode as in that mode we
56-
// replace wrapper component View with generated native wrapper RCTView. Avoid
57-
// adding functionality this component that you'd want to be available in both
58-
// dev and prod modes.
59-
return <RCTView {...this.props} />;
6062
}
6163
}
6264

Libraries/Image/Image.android.js

+38-38
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
* @flow
88
* @format
99
*/
10+
1011
'use strict';
1112

1213
var ImageResizeMode = require('ImageResizeMode');
@@ -18,6 +19,7 @@ var PropTypes = require('prop-types');
1819
var ReactNativeViewAttributes = require('ReactNativeViewAttributes');
1920
var StyleSheet = require('StyleSheet');
2021
var StyleSheetPropType = require('StyleSheetPropType');
22+
const TextAncestor = require('TextAncestor');
2123
var ViewPropTypes = require('ViewPropTypes');
2224

2325
var createReactClass = require('create-react-class');
@@ -26,8 +28,6 @@ var merge = require('merge');
2628
var requireNativeComponent = require('requireNativeComponent');
2729
var resolveAssetSource = require('resolveAssetSource');
2830

29-
const {ViewContextTypes} = require('ViewContext');
30-
3131
var {ImageLoader} = NativeModules;
3232

3333
let _requestId = 1;
@@ -202,8 +202,6 @@ var Image = createReactClass({
202202
validAttributes: ReactNativeViewAttributes.RCTView,
203203
},
204204

205-
contextTypes: ViewContextTypes,
206-
207205
render: function() {
208206
const source = resolveAssetSource(this.props.source);
209207
const defaultSource = resolveAssetSource(this.props.defaultSource);
@@ -236,42 +234,44 @@ var Image = createReactClass({
236234
);
237235
}
238236

239-
if (source && (source.uri || Array.isArray(source))) {
240-
let style;
241-
let sources;
242-
if (source.uri) {
243-
const {width, height} = source;
244-
style = flattenStyle([{width, height}, styles.base, this.props.style]);
245-
sources = [{uri: source.uri}];
246-
} else {
247-
style = flattenStyle([styles.base, this.props.style]);
248-
sources = source;
249-
}
250-
251-
const {onLoadStart, onLoad, onLoadEnd, onError} = this.props;
252-
const nativeProps = merge(this.props, {
253-
style,
254-
shouldNotifyLoadEvents: !!(
255-
onLoadStart ||
256-
onLoad ||
257-
onLoadEnd ||
258-
onError
259-
),
260-
src: sources,
261-
headers: source.headers,
262-
defaultSrc: defaultSource ? defaultSource.uri : null,
263-
loadingIndicatorSrc: loadingIndicatorSource
264-
? loadingIndicatorSource.uri
265-
: null,
266-
});
237+
if (!source || (!source.uri && !Array.isArray(source))) {
238+
return null;
239+
}
267240

268-
if (this.context.isInAParentText) {
269-
return <RCTTextInlineImage {...nativeProps} />;
270-
} else {
271-
return <RKImage {...nativeProps} />;
272-
}
241+
let style;
242+
let sources;
243+
if (source.uri) {
244+
const {width, height} = source;
245+
style = flattenStyle([{width, height}, styles.base, this.props.style]);
246+
sources = [{uri: source.uri}];
247+
} else {
248+
style = flattenStyle([styles.base, this.props.style]);
249+
sources = source;
273250
}
274-
return null;
251+
252+
const {onLoadStart, onLoad, onLoadEnd, onError} = this.props;
253+
const nativeProps = merge(this.props, {
254+
style,
255+
shouldNotifyLoadEvents: !!(onLoadStart || onLoad || onLoadEnd || onError),
256+
src: sources,
257+
headers: source.headers,
258+
defaultSrc: defaultSource ? defaultSource.uri : null,
259+
loadingIndicatorSrc: loadingIndicatorSource
260+
? loadingIndicatorSource.uri
261+
: null,
262+
});
263+
264+
return (
265+
<TextAncestor.Consumer>
266+
{hasTextAncestor =>
267+
hasTextAncestor ? (
268+
<RCTTextInlineImage {...nativeProps} />
269+
) : (
270+
<RKImage {...nativeProps} />
271+
)
272+
}
273+
</TextAncestor.Consumer>
274+
);
275275
},
276276
});
277277

Libraries/Text/Text.js

+14-15
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,17 @@
1212
const React = require('React');
1313
const ReactNative = require('ReactNative');
1414
const ReactNativeViewAttributes = require('ReactNativeViewAttributes');
15+
const TextAncestor = require('TextAncestor');
1516
const TextPropTypes = require('TextPropTypes');
1617
const Touchable = require('Touchable');
1718
const UIManager = require('UIManager');
1819

1920
const createReactNativeComponentClass = require('createReactNativeComponentClass');
2021
const mergeFast = require('mergeFast');
2122
const processColor = require('processColor');
22-
const {ViewContextTypes} = require('ViewContext');
2323

2424
import type {PressEvent} from 'CoreEventTypes';
2525
import type {TextProps} from 'TextProps';
26-
import type {ViewChildContext} from 'ViewContext';
2726

2827
type State = {
2928
isHighlighted: boolean,
@@ -61,8 +60,6 @@ const viewConfig = {
6160
*/
6261
class Text extends ReactNative.NativeComponent<TextProps, State> {
6362
static propTypes = TextPropTypes;
64-
static childContextTypes = ViewContextTypes;
65-
static contextTypes = ViewContextTypes;
6663

6764
static defaultProps = {
6865
accessible: true,
@@ -76,12 +73,6 @@ class Text extends ReactNative.NativeComponent<TextProps, State> {
7673

7774
viewConfig = viewConfig;
7875

79-
getChildContext(): ViewChildContext {
80-
return {
81-
isInAParentText: true,
82-
};
83-
}
84-
8576
_handlers: ?Object;
8677

8778
_hasPressHandler(): boolean {
@@ -215,11 +206,19 @@ class Text extends ReactNative.NativeComponent<TextProps, State> {
215206
style: [this.props.style, {color: 'magenta'}],
216207
};
217208
}
218-
if (this.context.isInAParentText) {
219-
return <RCTVirtualText {...newProps} />;
220-
} else {
221-
return <RCTText {...newProps} />;
222-
}
209+
return (
210+
<TextAncestor.Consumer>
211+
{hasTextAncestor =>
212+
hasTextAncestor ? (
213+
<RCTVirtualText {...newProps} />
214+
) : (
215+
<TextAncestor.Provider value={true}>
216+
<RCTText {...newProps} />
217+
</TextAncestor.Provider>
218+
)
219+
}
220+
</TextAncestor.Consumer>
221+
);
223222
}
224223
}
225224

Libraries/Components/View/ViewContext.js Libraries/Text/TextAncestor.js

+6-10
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,12 @@
77
* @flow
88
* @format
99
*/
10-
'use strict';
1110

12-
const PropTypes = require('prop-types');
11+
'use strict';
1312

14-
export type ViewChildContext = {|
15-
+isInAParentText: boolean,
16-
|};
13+
const React = require('React');
1714

18-
module.exports = {
19-
ViewContextTypes: {
20-
isInAParentText: PropTypes.bool,
21-
},
22-
};
15+
/**
16+
* Whether the current element is the descendant of a <Text> element.
17+
*/
18+
module.exports = React.createContext(false);

0 commit comments

Comments
 (0)