Skip to content

Commit

Permalink
Cleanup for shipping use_switch_modern
Browse files Browse the repository at this point in the history
Summary:
Changelog:
[General][Changed] - Refactor Switch component to functional and remove experimentation around it

Reviewed By: kacieb

Differential Revision: D28127518

fbshipit-source-id: c71d305a2caa8b3342ba603133c6e28c34410528
  • Loading branch information
Luna Wei authored and facebook-github-bot committed May 3, 2021
1 parent 2e0e3f7 commit ab66741
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 132 deletions.
200 changes: 86 additions & 114 deletions Libraries/Components/Switch/Switch.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import Platform from '../../Utilities/Platform';
import * as React from 'react';
import StyleSheet from '../../StyleSheet/StyleSheet';
import SwitchInjection from './SwitchInjection';

import AndroidSwitchNativeComponent, {
Commands as AndroidSwitchCommands,
Expand Down Expand Up @@ -86,6 +85,8 @@ export type Props = $ReadOnly<{|
*/
onValueChange?: ?(value: boolean) => Promise<void> | void,
|}>;
const returnsFalse = () => false;
const returnsTrue = () => true;

/**
Renders a boolean input.
Expand Down Expand Up @@ -128,132 +129,103 @@ export type Props = $ReadOnly<{|
export default App;
```
*/
class Switch extends React.Component<Props> {
_nativeSwitchRef: ?React.ElementRef<
export default function Switch(props: Props): React.Node {
const {
disabled,
ios_backgroundColor,
onChange,
onValueChange,
style,
thumbColor,
trackColor,
value,
...restProps
} = props;
const trackColorForFalse = trackColor?.false;
const trackColorForTrue = trackColor?.true;

const nativeSwitchRef = React.useRef<?React.ElementRef<
typeof SwitchNativeComponent | typeof AndroidSwitchNativeComponent,
>;
_lastNativeValue: ?boolean;

render(): React.Node {
const {
disabled,
ios_backgroundColor,
onChange,
onValueChange,
style,
thumbColor,
trackColor,
value,
...props
} = this.props;
>>(null);
const [native, setNative] = React.useState({value: null});

const trackColorForFalse = trackColor?.false;
const trackColorForTrue = trackColor?.true;

if (Platform.OS === 'android') {
const platformProps = {
enabled: disabled !== true,
on: value === true,
style,
thumbTintColor: thumbColor,
trackColorForFalse: trackColorForFalse,
trackColorForTrue: trackColorForTrue,
trackTintColor: value === true ? trackColorForTrue : trackColorForFalse,
};

return (
<AndroidSwitchNativeComponent
{...props}
{...platformProps}
accessibilityRole={props.accessibilityRole ?? 'switch'}
onChange={this._handleChange}
onResponderTerminationRequest={returnsFalse}
onStartShouldSetResponder={returnsTrue}
ref={this._handleSwitchNativeComponentRef}
/>
);
} else {
const platformProps = {
disabled,
onTintColor: trackColorForTrue,
style: StyleSheet.compose(
{height: 31, width: 51},
StyleSheet.compose(
style,
ios_backgroundColor == null
? null
: {
backgroundColor: ios_backgroundColor,
borderRadius: 16,
},
),
),
thumbTintColor: thumbColor,
tintColor: trackColorForFalse,
value: value === true,
};

return (
<SwitchNativeComponent
{...props}
{...platformProps}
accessibilityRole={props.accessibilityRole ?? 'switch'}
onChange={this._handleChange}
onResponderTerminationRequest={returnsFalse}
onStartShouldSetResponder={returnsTrue}
ref={this._handleSwitchNativeComponentRef}
/>
);
}
}
const handleChange = (event: SwitchChangeEvent) => {
onChange?.(event);
onValueChange?.(event.nativeEvent.value);
setNative({value: event.nativeEvent.value});
};

componentDidUpdate() {
React.useLayoutEffect(() => {
// This is necessary in case native updates the switch and JS decides
// that the update should be ignored and we should stick with the value
// that we have in JS.
const value = this.props.value === true;
const nativeValue = this._lastNativeValue !== value ? value : null;

const jsValue = value === true;
const shouldUpdateNativeSwitch = native.value !== jsValue;
if (
nativeValue != null &&
this._nativeSwitchRef &&
this._nativeSwitchRef.setNativeProps
shouldUpdateNativeSwitch &&
nativeSwitchRef.current?.setNativeProps != null
) {
if (Platform.OS === 'android') {
AndroidSwitchCommands.setNativeValue(
this._nativeSwitchRef,
nativeValue,
);
AndroidSwitchCommands.setNativeValue(nativeSwitchRef.current, jsValue);
} else {
SwitchCommands.setValue(this._nativeSwitchRef, nativeValue);
SwitchCommands.setValue(nativeSwitchRef.current, jsValue);
}
}
}
}, [value, native]);

_handleChange = (event: SwitchChangeEvent) => {
if (this.props.onChange != null) {
this.props.onChange(event);
}

if (this.props.onValueChange != null) {
this.props.onValueChange(event.nativeEvent.value);
}
if (Platform.OS === 'android') {
const platformProps = {
enabled: disabled !== true,
on: value === true,
style,
thumbTintColor: thumbColor,
trackColorForFalse: trackColorForFalse,
trackColorForTrue: trackColorForTrue,
trackTintColor: value === true ? trackColorForTrue : trackColorForFalse,
};

this._lastNativeValue = event.nativeEvent.value;
this.forceUpdate();
};
return (
<AndroidSwitchNativeComponent
{...restProps}
{...platformProps}
accessibilityRole={props.accessibilityRole ?? 'switch'}
onChange={handleChange}
onResponderTerminationRequest={returnsFalse}
onStartShouldSetResponder={returnsTrue}
ref={nativeSwitchRef}
/>
);
} else {
const platformProps = {
disabled,
onTintColor: trackColorForTrue,
style: StyleSheet.compose(
{height: 31, width: 51},
StyleSheet.compose(
style,
ios_backgroundColor == null
? null
: {
backgroundColor: ios_backgroundColor,
borderRadius: 16,
},
),
),
thumbTintColor: thumbColor,
tintColor: trackColorForFalse,
value: value === true,
};

_handleSwitchNativeComponentRef = (
ref: ?React.ElementRef<
typeof SwitchNativeComponent | typeof AndroidSwitchNativeComponent,
>,
) => {
this._nativeSwitchRef = ref;
};
return (
<SwitchNativeComponent
{...restProps}
{...platformProps}
accessibilityRole={props.accessibilityRole ?? 'switch'}
onChange={handleChange}
onResponderTerminationRequest={returnsFalse}
onStartShouldSetResponder={returnsTrue}
ref={nativeSwitchRef}
/>
);
}
}

const returnsFalse = () => false;
const returnsTrue = () => true;

module.exports = (SwitchInjection.unstable_Switch ??
Switch: React.AbstractComponent<React.ElementConfig<typeof Switch>>);
17 changes: 0 additions & 17 deletions Libraries/Components/Switch/SwitchInjection.js

This file was deleted.

2 changes: 1 addition & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ module.exports = {
return require('./Libraries/Components/StatusBar/StatusBar');
},
get Switch(): Switch {
return require('./Libraries/Components/Switch/Switch');
return require('./Libraries/Components/Switch/Switch').default;
},
get Text(): Text {
return require('./Libraries/Text/Text');
Expand Down

0 comments on commit ab66741

Please sign in to comment.