Skip to content

Commit 147c38a

Browse files
nissy-devfacebook-github-bot
authored andcommitted
remove createReactClass from ToolbarAndroid/ToolbarAndroid.android.js (#21893)
Summary: Related to #21581 . Removed createReactClass from the Libraries/Components/ToolbarAndroid/ToolbarAndroid.android.js - [x] npm run prettier - [x] npm run flow-check-ios - [x] npm run flow-check-android [GENERAL] [ENHANCEMENT] [Libraries/Components/ToolbarAndroid/ToolbarAndroid.android.js] - remove createReactClass dependency Pull Request resolved: #21893 Reviewed By: TheSavior Differential Revision: D12826971 Pulled By: RSNara fbshipit-source-id: 3d3fb88a3c9faf3ef89e386ca0d41d939f5d14dd
1 parent 79712c3 commit 147c38a

File tree

1 file changed

+167
-128
lines changed

1 file changed

+167
-128
lines changed

Libraries/Components/ToolbarAndroid/ToolbarAndroid.android.js

+167-128
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,22 @@
55
* LICENSE file in the root directory of this source tree.
66
*
77
* @format
8+
* @flow
89
*/
910

1011
'use strict';
1112

12-
const DeprecatedColorPropType = require('DeprecatedColorPropType');
13-
const DeprecatedViewPropTypes = require('DeprecatedViewPropTypes');
14-
const Image = require('Image');
15-
const NativeMethodsMixin = require('NativeMethodsMixin');
16-
const PropTypes = require('prop-types');
1713
const React = require('React');
1814
const UIManager = require('UIManager');
1915

20-
const createReactClass = require('create-react-class');
2116
const requireNativeComponent = require('requireNativeComponent');
2217
const resolveAssetSource = require('resolveAssetSource');
2318

24-
const optionalImageSource = PropTypes.oneOfType([
25-
Image.propTypes.source,
26-
// Image.propTypes.source is required but we want it to be optional, so we OR
27-
// it with a nullable propType.
28-
PropTypes.oneOf([]),
29-
]);
19+
import type {SyntheticEvent} from 'CoreEventTypes';
20+
import type {ImageSource} from 'ImageSource';
21+
import type {ColorValue} from 'StyleSheetTypes';
22+
import type {ViewProps} from 'ViewPropTypes';
23+
import type {NativeComponent} from 'ReactNative';
3024

3125
/**
3226
* React component that wraps the Android-only [`Toolbar` widget][0]. A Toolbar can display a logo,
@@ -63,124 +57,157 @@ const optionalImageSource = PropTypes.oneOfType([
6357
*
6458
* [0]: https://developer.android.com/reference/android/support/v7/widget/Toolbar.html
6559
*/
66-
const ToolbarAndroid = createReactClass({
67-
displayName: 'ToolbarAndroid',
68-
mixins: [NativeMethodsMixin],
69-
70-
propTypes: {
71-
...DeprecatedViewPropTypes,
72-
/**
73-
* Sets possible actions on the toolbar as part of the action menu. These are displayed as icons
74-
* or text on the right side of the widget. If they don't fit they are placed in an 'overflow'
75-
* menu.
76-
*
77-
* This property takes an array of objects, where each object has the following keys:
78-
*
79-
* * `title`: **required**, the title of this action
80-
* * `icon`: the icon for this action, e.g. `require('./some_icon.png')`
81-
* * `show`: when to show this action as an icon or hide it in the overflow menu: `always`,
82-
* `ifRoom` or `never`
83-
* * `showWithText`: boolean, whether to show text alongside the icon or not
84-
*/
85-
actions: PropTypes.arrayOf(
86-
PropTypes.shape({
87-
title: PropTypes.string.isRequired,
88-
icon: optionalImageSource,
89-
show: PropTypes.oneOf(['always', 'ifRoom', 'never']),
90-
showWithText: PropTypes.bool,
91-
}),
92-
),
93-
/**
94-
* Sets the toolbar logo.
95-
*/
96-
logo: optionalImageSource,
97-
/**
98-
* Sets the navigation icon.
99-
*/
100-
navIcon: optionalImageSource,
101-
/**
102-
* Callback that is called when an action is selected. The only argument that is passed to the
103-
* callback is the position of the action in the actions array.
104-
*/
105-
onActionSelected: PropTypes.func,
106-
/**
107-
* Callback called when the icon is selected.
108-
*/
109-
onIconClicked: PropTypes.func,
110-
/**
111-
* Sets the overflow icon.
112-
*/
113-
overflowIcon: optionalImageSource,
114-
/**
115-
* Sets the toolbar subtitle.
116-
*/
117-
subtitle: PropTypes.string,
118-
/**
119-
* Sets the toolbar subtitle color.
120-
*/
121-
subtitleColor: DeprecatedColorPropType,
122-
/**
123-
* Sets the toolbar title.
124-
*/
125-
title: PropTypes.string,
126-
/**
127-
* Sets the toolbar title color.
128-
*/
129-
titleColor: DeprecatedColorPropType,
130-
/**
131-
* Sets the content inset for the toolbar starting edge.
132-
*
133-
* The content inset affects the valid area for Toolbar content other than
134-
* the navigation button and menu. Insets define the minimum margin for
135-
* these components and can be used to effectively align Toolbar content
136-
* along well-known gridlines.
137-
*/
138-
contentInsetStart: PropTypes.number,
139-
/**
140-
* Sets the content inset for the toolbar ending edge.
141-
*
142-
* The content inset affects the valid area for Toolbar content other than
143-
* the navigation button and menu. Insets define the minimum margin for
144-
* these components and can be used to effectively align Toolbar content
145-
* along well-known gridlines.
146-
*/
147-
contentInsetEnd: PropTypes.number,
148-
/**
149-
* Used to set the toolbar direction to RTL.
150-
* In addition to this property you need to add
151-
*
152-
* android:supportsRtl="true"
153-
*
154-
* to your application AndroidManifest.xml and then call
155-
* `setLayoutDirection(LayoutDirection.RTL)` in your MainActivity
156-
* `onCreate` method.
157-
*/
158-
rtl: PropTypes.bool,
159-
/**
160-
* Used to locate this view in end-to-end tests.
161-
*/
162-
testID: PropTypes.string,
163-
},
16460

165-
render: function() {
166-
const nativeProps = {
167-
...this.props,
61+
const NativeToolbar = requireNativeComponent('ToolbarAndroid');
62+
63+
type Action = $ReadOnly<{|
64+
title: string,
65+
icon?: ?ImageSource,
66+
show?: 'always' | 'ifRoom' | 'never',
67+
showWithText?: boolean,
68+
|}>;
69+
70+
type ToolbarAndroidChangeEvent = SyntheticEvent<
71+
$ReadOnly<{|
72+
position: number,
73+
|}>,
74+
>;
75+
76+
type ToolbarAndroidProps = $ReadOnly<{|
77+
...ViewProps,
78+
/**
79+
* or text on the right side of the widget. If they don't fit they are placed in an 'overflow'
80+
* Sets possible actions on the toolbar as part of the action menu. These are displayed as icons
81+
* menu.
82+
*
83+
* This property takes an array of objects, where each object has the following keys:
84+
*
85+
* * `title`: **required**, the title of this action
86+
* * `icon`: the icon for this action, e.g. `require('./some_icon.png')`
87+
* * `show`: when to show this action as an icon or hide it in the overflow menu: `always`,
88+
* `ifRoom` or `never`
89+
* * `showWithText`: boolean, whether to show text alongside the icon or not
90+
*/
91+
actions?: ?Array<Action>,
92+
/**
93+
* Sets the toolbar logo.
94+
*/
95+
logo?: ?ImageSource,
96+
/**
97+
* Sets the navigation icon.
98+
*/
99+
navIcon?: ?ImageSource,
100+
/**
101+
* Callback that is called when an action is selected. The only argument that is passed to the
102+
* callback is the position of the action in the actions array.
103+
*/
104+
onActionSelected?: ?(position: number) => void,
105+
/**
106+
* Callback called when the icon is selected.
107+
*/
108+
onIconClicked?: ?() => void,
109+
/**
110+
* Sets the overflow icon.
111+
*/
112+
overflowIcon?: ?ImageSource,
113+
/**
114+
* Sets the toolbar subtitle.
115+
*/
116+
subtitle?: ?string,
117+
/**
118+
* Sets the toolbar subtitle color.
119+
*/
120+
subtitleColor?: ?ColorValue,
121+
/**
122+
* Sets the toolbar title.
123+
*/
124+
title?: ?Stringish,
125+
/**
126+
* Sets the toolbar title color.
127+
*/
128+
titleColor?: ?ColorValue,
129+
/**
130+
* Sets the content inset for the toolbar starting edge.
131+
*
132+
* The content inset affects the valid area for Toolbar content other than
133+
* the navigation button and menu. Insets define the minimum margin for
134+
* these components and can be used to effectively align Toolbar content
135+
* along well-known gridlines.
136+
*/
137+
contentInsetStart?: ?number,
138+
/**
139+
* Sets the content inset for the toolbar ending edge.
140+
*
141+
* The content inset affects the valid area for Toolbar content other than
142+
* the navigation button and menu. Insets define the minimum margin for
143+
* these components and can be used to effectively align Toolbar content
144+
* along well-known gridlines.
145+
*/
146+
contentInsetEnd?: ?number,
147+
/**
148+
* Used to set the toolbar direction to RTL.
149+
* In addition to this property you need to add
150+
*
151+
* android:supportsRtl="true"
152+
*
153+
* to your application AndroidManifest.xml and then call
154+
* `setLayoutDirection(LayoutDirection.RTL)` in your MainActivity
155+
* `onCreate` method.
156+
*/
157+
rtl?: ?boolean,
158+
/**
159+
* Used to locate this view in end-to-end tests.
160+
*/
161+
testID?: ?string,
162+
|}>;
163+
164+
type Props = $ReadOnly<{|
165+
...ToolbarAndroidProps,
166+
forwardedRef: ?React.Ref<typeof NativeToolbar>,
167+
|}>;
168+
169+
class ToolbarAndroid extends React.Component<Props> {
170+
_onSelect = (event: ToolbarAndroidChangeEvent) => {
171+
const position = event.nativeEvent.position;
172+
if (position === -1) {
173+
this.props.onIconClicked && this.props.onIconClicked();
174+
} else {
175+
this.props.onActionSelected && this.props.onActionSelected(position);
176+
}
177+
};
178+
179+
render() {
180+
const {
181+
onIconClicked,
182+
onActionSelected,
183+
forwardedRef,
184+
...otherProps
185+
} = this.props;
186+
187+
const nativeProps: {...typeof otherProps, nativeActions?: Array<Action>} = {
188+
...otherProps,
168189
};
190+
169191
if (this.props.logo) {
170192
nativeProps.logo = resolveAssetSource(this.props.logo);
171193
}
194+
172195
if (this.props.navIcon) {
173196
nativeProps.navIcon = resolveAssetSource(this.props.navIcon);
174197
}
198+
175199
if (this.props.overflowIcon) {
176200
nativeProps.overflowIcon = resolveAssetSource(this.props.overflowIcon);
177201
}
202+
178203
if (this.props.actions) {
179204
const nativeActions = [];
180205
for (let i = 0; i < this.props.actions.length; i++) {
181206
const action = {
182-
...this.props.actions[i],
207+
icon: this.props.actions[i].icon,
208+
show: this.props.actions[i].show,
183209
};
210+
184211
if (action.icon) {
185212
action.icon = resolveAssetSource(action.icon);
186213
}
@@ -189,24 +216,36 @@ const ToolbarAndroid = createReactClass({
189216
'ToolbarAndroid',
190217
).Constants.ShowAsAction[action.show];
191218
}
192-
nativeActions.push(action);
219+
220+
nativeActions.push({
221+
...this.props.actions[i],
222+
...action,
223+
});
193224
}
225+
194226
nativeProps.nativeActions = nativeActions;
195227
}
196228

197-
return <NativeToolbar onSelect={this._onSelect} {...nativeProps} />;
198-
},
229+
return (
230+
<NativeToolbar
231+
onSelect={this._onSelect}
232+
{...nativeProps}
233+
ref={forwardedRef}
234+
/>
235+
);
236+
}
237+
}
199238

200-
_onSelect: function(event) {
201-
const position = event.nativeEvent.position;
202-
if (position === -1) {
203-
this.props.onIconClicked && this.props.onIconClicked();
204-
} else {
205-
this.props.onActionSelected && this.props.onActionSelected(position);
206-
}
239+
// $FlowFixMe - TODO T29156721 `React.forwardRef` is not defined in Flow, yet.
240+
const ToolbarAndroidToExport = React.forwardRef(
241+
(
242+
props: ToolbarAndroidProps,
243+
forwardedRef: ?React.Ref<typeof NativeToolbar>,
244+
) => {
245+
return <ToolbarAndroid {...props} forwardedRef={forwardedRef} />;
207246
},
208-
});
209-
210-
const NativeToolbar = requireNativeComponent('ToolbarAndroid');
247+
);
211248

212-
module.exports = ToolbarAndroid;
249+
module.exports = (ToolbarAndroidToExport: Class<
250+
NativeComponent<ToolbarAndroidProps>,
251+
>);

0 commit comments

Comments
 (0)