Skip to content

Commit 28de61e

Browse files
empyricalfacebook-github-bot
authored andcommitted
CheckBox: Convert NativeMethodsMixin to forwardedRef, convert to class (#21585)
Summary: This PR converts the use of `NativeMethodsMixin` in `CheckBox.android.js`, and converts it to an ES6-style class. Pull Request resolved: #21585 Reviewed By: TheSavior Differential Revision: D12827768 Pulled By: RSNara fbshipit-source-id: c113c221335e61e015a20bbb6bcff5f9837f9022
1 parent 14e1628 commit 28de61e

File tree

1 file changed

+105
-71
lines changed

1 file changed

+105
-71
lines changed

Libraries/Components/CheckBox/CheckBox.android.js

+105-71
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,76 @@
99
*/
1010
'use strict';
1111

12-
const DeprecatedViewPropTypes = require('DeprecatedViewPropTypes');
13-
const NativeMethodsMixin = require('NativeMethodsMixin');
14-
const PropTypes = require('prop-types');
1512
const React = require('React');
1613
const StyleSheet = require('StyleSheet');
1714

18-
const createReactClass = require('create-react-class');
1915
const requireNativeComponent = require('requireNativeComponent');
16+
const nullthrows = require('nullthrows');
17+
const setAndForwardRef = require('setAndForwardRef');
2018

21-
const RCTCheckBox = requireNativeComponent('AndroidCheckBox');
19+
import type {ViewProps} from 'ViewPropTypes';
20+
import type {SyntheticEvent} from 'CoreEventTypes';
21+
import type {NativeComponent} from 'ReactNative';
2222

23-
type DefaultProps = {
24-
value: boolean,
25-
disabled: boolean,
26-
};
23+
type CheckBoxEvent = SyntheticEvent<
24+
$ReadOnly<{|
25+
target: number,
26+
value: boolean,
27+
|}>,
28+
>;
29+
30+
type CommonProps = $ReadOnly<{|
31+
...ViewProps,
32+
33+
/**
34+
* Used in case the props change removes the component.
35+
*/
36+
onChange?: ?(event: CheckBoxEvent) => mixed,
37+
38+
/**
39+
* Invoked with the new value when the value changes.
40+
*/
41+
onValueChange?: ?(value: boolean) => mixed,
42+
43+
/**
44+
* Used to locate this view in end-to-end tests.
45+
*/
46+
testID?: ?string,
47+
|}>;
48+
49+
type NativeProps = $ReadOnly<{|
50+
...CommonProps,
51+
52+
on?: ?boolean,
53+
enabled?: boolean,
54+
|}>;
55+
56+
type CheckBoxNativeType = Class<NativeComponent<NativeProps>>;
57+
58+
type Props = $ReadOnly<{|
59+
...CommonProps,
60+
61+
/**
62+
* The value of the checkbox. If true the checkbox will be turned on.
63+
* Default value is false.
64+
*/
65+
value?: ?boolean,
66+
67+
/**
68+
* If true the user won't be able to toggle the checkbox.
69+
* Default value is false.
70+
*/
71+
disabled?: ?boolean,
72+
73+
/**
74+
* Used to get the ref for the native checkbox
75+
*/
76+
forwardedRef?: ?React.Ref<CheckBoxNativeType>,
77+
|}>;
78+
79+
const RCTCheckBox = ((requireNativeComponent(
80+
'AndroidCheckBox',
81+
): any): CheckBoxNativeType);
2782

2883
/**
2984
* Renders a boolean input (Android only).
@@ -80,85 +135,64 @@ type DefaultProps = {
80135
* @keyword checkbox
81136
* @keyword toggle
82137
*/
83-
let CheckBox = createReactClass({
84-
displayName: 'CheckBox',
85-
propTypes: {
86-
...DeprecatedViewPropTypes,
87-
/**
88-
* The value of the checkbox. If true the checkbox will be turned on.
89-
* Default value is false.
90-
*/
91-
value: PropTypes.bool,
92-
/**
93-
* If true the user won't be able to toggle the checkbox.
94-
* Default value is false.
95-
*/
96-
disabled: PropTypes.bool,
97-
/**
98-
* Used in case the props change removes the component.
99-
*/
100-
onChange: PropTypes.func,
101-
/**
102-
* Invoked with the new value when the value changes.
103-
*/
104-
onValueChange: PropTypes.func,
105-
/**
106-
* Used to locate this view in end-to-end tests.
107-
*/
108-
testID: PropTypes.string,
109-
},
138+
class CheckBox extends React.Component<Props> {
139+
_nativeRef: ?React.ElementRef<CheckBoxNativeType> = null;
140+
_setNativeRef = setAndForwardRef({
141+
getForwardedRef: () => this.props.forwardedRef,
142+
setLocalRef: ref => {
143+
this._nativeRef = ref;
144+
},
145+
});
110146

111-
getDefaultProps: function(): DefaultProps {
112-
return {
113-
value: false,
114-
disabled: false,
115-
};
116-
},
117-
118-
mixins: [NativeMethodsMixin],
119-
120-
_rctCheckBox: {},
121-
_onChange: function(event: Object) {
122-
this._rctCheckBox.setNativeProps({value: this.props.value});
147+
_onChange = (event: CheckBoxEvent) => {
148+
const value = this.props.value ?? false;
149+
nullthrows(this._nativeRef).setNativeProps({value: value});
123150
// Change the props after the native props are set in case the props
124151
// change removes the component
125152
this.props.onChange && this.props.onChange(event);
126153
this.props.onValueChange &&
127154
this.props.onValueChange(event.nativeEvent.value);
128-
},
155+
};
129156

130-
render: function() {
131-
let props = {...this.props};
132-
props.onStartShouldSetResponder = () => true;
133-
props.onResponderTerminationRequest = () => false;
134-
/* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found
135-
* when making Flow check .android.js files. */
136-
props.enabled = !this.props.disabled;
137-
/* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found
138-
* when making Flow check .android.js files. */
139-
props.on = this.props.value;
140-
props.style = [styles.rctCheckBox, this.props.style];
157+
render() {
158+
const {disabled: _, value: __, style, forwardedRef, ...props} = this.props;
159+
const disabled = this.props.disabled ?? false;
160+
const value = this.props.value ?? false;
161+
162+
const nativeProps = {
163+
...props,
164+
onStartShouldSetResponder: () => true,
165+
onResponderTerminationRequest: () => false,
166+
enabled: !disabled,
167+
on: value,
168+
style: [styles.rctCheckBox, style],
169+
};
141170

142171
return (
143172
<RCTCheckBox
144-
{...props}
145-
ref={ref => {
146-
/* $FlowFixMe(>=0.53.0 site=react_native_fb,react_native_oss) This
147-
* comment suppresses an error when upgrading Flow's support for
148-
* React. To see the error delete this comment and run Flow. */
149-
this._rctCheckBox = ref;
150-
}}
173+
{...nativeProps}
174+
ref={this._setNativeRef}
151175
onChange={this._onChange}
152176
/>
153177
);
154-
},
155-
});
178+
}
179+
}
156180

157-
let styles = StyleSheet.create({
181+
const styles = StyleSheet.create({
158182
rctCheckBox: {
159183
height: 32,
160184
width: 32,
161185
},
162186
});
163187

164-
module.exports = CheckBox;
188+
/**
189+
* Can't use CheckBoxNativeType because it has different props
190+
*/
191+
type CheckBoxType = Class<NativeComponent<Props>>;
192+
193+
// $FlowFixMe - TODO T29156721 `React.forwardRef` is not defined in Flow, yet.
194+
const CheckBoxWithRef = React.forwardRef(function CheckBoxWithRef(props, ref) {
195+
return <CheckBox {...props} forwardedRef={ref} />;
196+
});
197+
198+
module.exports = (CheckBoxWithRef: CheckBoxType);

0 commit comments

Comments
 (0)