Skip to content

Commit ab66741

Browse files
Luna Weifacebook-github-bot
Luna Wei
authored andcommittedMay 3, 2021
Cleanup for shipping use_switch_modern
Summary: Changelog: [General][Changed] - Refactor Switch component to functional and remove experimentation around it Reviewed By: kacieb Differential Revision: D28127518 fbshipit-source-id: c71d305a2caa8b3342ba603133c6e28c34410528
1 parent 2e0e3f7 commit ab66741

File tree

3 files changed

+87
-132
lines changed

3 files changed

+87
-132
lines changed
 

‎Libraries/Components/Switch/Switch.js

+86-114
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
import Platform from '../../Utilities/Platform';
1313
import * as React from 'react';
1414
import StyleSheet from '../../StyleSheet/StyleSheet';
15-
import SwitchInjection from './SwitchInjection';
1615

1716
import AndroidSwitchNativeComponent, {
1817
Commands as AndroidSwitchCommands,
@@ -86,6 +85,8 @@ export type Props = $ReadOnly<{|
8685
*/
8786
onValueChange?: ?(value: boolean) => Promise<void> | void,
8887
|}>;
88+
const returnsFalse = () => false;
89+
const returnsTrue = () => true;
8990

9091
/**
9192
Renders a boolean input.
@@ -128,132 +129,103 @@ export type Props = $ReadOnly<{|
128129
export default App;
129130
```
130131
*/
131-
class Switch extends React.Component<Props> {
132-
_nativeSwitchRef: ?React.ElementRef<
132+
export default function Switch(props: Props): React.Node {
133+
const {
134+
disabled,
135+
ios_backgroundColor,
136+
onChange,
137+
onValueChange,
138+
style,
139+
thumbColor,
140+
trackColor,
141+
value,
142+
...restProps
143+
} = props;
144+
const trackColorForFalse = trackColor?.false;
145+
const trackColorForTrue = trackColor?.true;
146+
147+
const nativeSwitchRef = React.useRef<?React.ElementRef<
133148
typeof SwitchNativeComponent | typeof AndroidSwitchNativeComponent,
134-
>;
135-
_lastNativeValue: ?boolean;
136-
137-
render(): React.Node {
138-
const {
139-
disabled,
140-
ios_backgroundColor,
141-
onChange,
142-
onValueChange,
143-
style,
144-
thumbColor,
145-
trackColor,
146-
value,
147-
...props
148-
} = this.props;
149+
>>(null);
150+
const [native, setNative] = React.useState({value: null});
149151

150-
const trackColorForFalse = trackColor?.false;
151-
const trackColorForTrue = trackColor?.true;
152-
153-
if (Platform.OS === 'android') {
154-
const platformProps = {
155-
enabled: disabled !== true,
156-
on: value === true,
157-
style,
158-
thumbTintColor: thumbColor,
159-
trackColorForFalse: trackColorForFalse,
160-
trackColorForTrue: trackColorForTrue,
161-
trackTintColor: value === true ? trackColorForTrue : trackColorForFalse,
162-
};
163-
164-
return (
165-
<AndroidSwitchNativeComponent
166-
{...props}
167-
{...platformProps}
168-
accessibilityRole={props.accessibilityRole ?? 'switch'}
169-
onChange={this._handleChange}
170-
onResponderTerminationRequest={returnsFalse}
171-
onStartShouldSetResponder={returnsTrue}
172-
ref={this._handleSwitchNativeComponentRef}
173-
/>
174-
);
175-
} else {
176-
const platformProps = {
177-
disabled,
178-
onTintColor: trackColorForTrue,
179-
style: StyleSheet.compose(
180-
{height: 31, width: 51},
181-
StyleSheet.compose(
182-
style,
183-
ios_backgroundColor == null
184-
? null
185-
: {
186-
backgroundColor: ios_backgroundColor,
187-
borderRadius: 16,
188-
},
189-
),
190-
),
191-
thumbTintColor: thumbColor,
192-
tintColor: trackColorForFalse,
193-
value: value === true,
194-
};
195-
196-
return (
197-
<SwitchNativeComponent
198-
{...props}
199-
{...platformProps}
200-
accessibilityRole={props.accessibilityRole ?? 'switch'}
201-
onChange={this._handleChange}
202-
onResponderTerminationRequest={returnsFalse}
203-
onStartShouldSetResponder={returnsTrue}
204-
ref={this._handleSwitchNativeComponentRef}
205-
/>
206-
);
207-
}
208-
}
152+
const handleChange = (event: SwitchChangeEvent) => {
153+
onChange?.(event);
154+
onValueChange?.(event.nativeEvent.value);
155+
setNative({value: event.nativeEvent.value});
156+
};
209157

210-
componentDidUpdate() {
158+
React.useLayoutEffect(() => {
211159
// This is necessary in case native updates the switch and JS decides
212160
// that the update should be ignored and we should stick with the value
213161
// that we have in JS.
214-
const value = this.props.value === true;
215-
const nativeValue = this._lastNativeValue !== value ? value : null;
216-
162+
const jsValue = value === true;
163+
const shouldUpdateNativeSwitch = native.value !== jsValue;
217164
if (
218-
nativeValue != null &&
219-
this._nativeSwitchRef &&
220-
this._nativeSwitchRef.setNativeProps
165+
shouldUpdateNativeSwitch &&
166+
nativeSwitchRef.current?.setNativeProps != null
221167
) {
222168
if (Platform.OS === 'android') {
223-
AndroidSwitchCommands.setNativeValue(
224-
this._nativeSwitchRef,
225-
nativeValue,
226-
);
169+
AndroidSwitchCommands.setNativeValue(nativeSwitchRef.current, jsValue);
227170
} else {
228-
SwitchCommands.setValue(this._nativeSwitchRef, nativeValue);
171+
SwitchCommands.setValue(nativeSwitchRef.current, jsValue);
229172
}
230173
}
231-
}
174+
}, [value, native]);
232175

233-
_handleChange = (event: SwitchChangeEvent) => {
234-
if (this.props.onChange != null) {
235-
this.props.onChange(event);
236-
}
237-
238-
if (this.props.onValueChange != null) {
239-
this.props.onValueChange(event.nativeEvent.value);
240-
}
176+
if (Platform.OS === 'android') {
177+
const platformProps = {
178+
enabled: disabled !== true,
179+
on: value === true,
180+
style,
181+
thumbTintColor: thumbColor,
182+
trackColorForFalse: trackColorForFalse,
183+
trackColorForTrue: trackColorForTrue,
184+
trackTintColor: value === true ? trackColorForTrue : trackColorForFalse,
185+
};
241186

242-
this._lastNativeValue = event.nativeEvent.value;
243-
this.forceUpdate();
244-
};
187+
return (
188+
<AndroidSwitchNativeComponent
189+
{...restProps}
190+
{...platformProps}
191+
accessibilityRole={props.accessibilityRole ?? 'switch'}
192+
onChange={handleChange}
193+
onResponderTerminationRequest={returnsFalse}
194+
onStartShouldSetResponder={returnsTrue}
195+
ref={nativeSwitchRef}
196+
/>
197+
);
198+
} else {
199+
const platformProps = {
200+
disabled,
201+
onTintColor: trackColorForTrue,
202+
style: StyleSheet.compose(
203+
{height: 31, width: 51},
204+
StyleSheet.compose(
205+
style,
206+
ios_backgroundColor == null
207+
? null
208+
: {
209+
backgroundColor: ios_backgroundColor,
210+
borderRadius: 16,
211+
},
212+
),
213+
),
214+
thumbTintColor: thumbColor,
215+
tintColor: trackColorForFalse,
216+
value: value === true,
217+
};
245218

246-
_handleSwitchNativeComponentRef = (
247-
ref: ?React.ElementRef<
248-
typeof SwitchNativeComponent | typeof AndroidSwitchNativeComponent,
249-
>,
250-
) => {
251-
this._nativeSwitchRef = ref;
252-
};
219+
return (
220+
<SwitchNativeComponent
221+
{...restProps}
222+
{...platformProps}
223+
accessibilityRole={props.accessibilityRole ?? 'switch'}
224+
onChange={handleChange}
225+
onResponderTerminationRequest={returnsFalse}
226+
onStartShouldSetResponder={returnsTrue}
227+
ref={nativeSwitchRef}
228+
/>
229+
);
230+
}
253231
}
254-
255-
const returnsFalse = () => false;
256-
const returnsTrue = () => true;
257-
258-
module.exports = (SwitchInjection.unstable_Switch ??
259-
Switch: React.AbstractComponent<React.ElementConfig<typeof Switch>>);

‎Libraries/Components/Switch/SwitchInjection.js

-17
This file was deleted.

‎index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ module.exports = {
244244
return require('./Libraries/Components/StatusBar/StatusBar');
245245
},
246246
get Switch(): Switch {
247-
return require('./Libraries/Components/Switch/Switch');
247+
return require('./Libraries/Components/Switch/Switch').default;
248248
},
249249
get Text(): Text {
250250
return require('./Libraries/Text/Text');

0 commit comments

Comments
 (0)
Please sign in to comment.