Skip to content

Commit aa8c072

Browse files
javachefacebook-github-bot
authored andcommitted
Fix Switch broken as controlled component (facebook#50928)
Summary: Pull Request resolved: facebook#50928 This broke in D72979663, since we relied on the object identify of `native` changing to correctly reset the native state back to the controlled JS state. Changelog: [General][Fixed] Fixed switches correctly reverting to controlled state Reviewed By: vzaidman Differential Revision: D73653323 fbshipit-source-id: d6ca8a31d9f08a339c7acf6bba264137690dd794
1 parent de165a2 commit aa8c072

File tree

1 file changed

+8
-4
lines changed
  • packages/react-native/Libraries/Components/Switch

1 file changed

+8
-4
lines changed

packages/react-native/Libraries/Components/Switch/Switch.js

+8-4
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import SwitchNativeComponent, {
2222
Commands as SwitchCommands,
2323
} from './SwitchNativeComponent';
2424
import * as React from 'react';
25+
import {useLayoutEffect, useRef, useState} from 'react';
2526

2627
export type SwitchPropsIOS = {
2728
/**
@@ -179,13 +180,16 @@ const Switch: component(
179180
const trackColorForFalse = trackColor?.false;
180181
const trackColorForTrue = trackColor?.true;
181182

182-
const nativeSwitchRef = React.useRef<React.ElementRef<
183+
const nativeSwitchRef = useRef<React.ElementRef<
183184
typeof SwitchNativeComponent | typeof AndroidSwitchNativeComponent,
184185
> | null>(null);
185186

186187
const ref = useMergeRefs(nativeSwitchRef, forwardedRef);
187188

188-
const [native, setNative] = React.useState({value: (null: ?boolean)});
189+
// We wrap the native state in an object to force the layout-effect
190+
// below to re-run whenever we get an update from native, even if it's
191+
// not different from the previous native state.
192+
const [native, setNative] = useState({value: (null: ?boolean)});
189193

190194
const handleChange = (event: SwitchChangeEvent) => {
191195
// $FlowFixMe[unused-promise]
@@ -195,7 +199,7 @@ const Switch: component(
195199
setNative({value: event.nativeEvent.value});
196200
};
197201

198-
React.useLayoutEffect(() => {
202+
useLayoutEffect(() => {
199203
// This is necessary in case native updates the switch and JS decides
200204
// that the update should be ignored and we should stick with the value
201205
// that we have in JS.
@@ -213,7 +217,7 @@ const Switch: component(
213217
SwitchCommands.setValue(nativeSwitchRef.current, jsValue);
214218
}
215219
}
216-
}, [value, native.value]);
220+
}, [value, native]);
217221

218222
if (Platform.OS === 'android') {
219223
const {onTintColor, tintColor, ...androidProps} = restProps;

0 commit comments

Comments
 (0)