diff --git a/src/components/TextInput/TextInput.tsx b/src/components/TextInput/TextInput.tsx index b254448dd1..2fc72d4416 100644 --- a/src/components/TextInput/TextInput.tsx +++ b/src/components/TextInput/TextInput.tsx @@ -207,8 +207,8 @@ const TextInput = React.forwardRef( }: TextInputProps, ref ) => { - const validInputValue = - rest.value !== undefined ? rest.value : rest.defaultValue; + const isControlled = rest.value !== undefined; + const validInputValue = isControlled ? rest.value : rest.defaultValue; const { current: labeled } = React.useRef( new Animated.Value(validInputValue ? 0 : 1) @@ -220,9 +220,12 @@ const TextInput = React.forwardRef( const [placeholder, setPlaceholder] = React.useState( '' ); - const [value, setValue] = React.useState( - validInputValue - ); + const [uncontrolledValue, setUncontrolledValue] = React.useState< + string | undefined + >(validInputValue); + // Use value from props instead of local state when input is controlled + const value = isControlled ? rest.value : uncontrolledValue; + const [labelLayout, setLabelLayout] = React.useState<{ measured: boolean; width: number; @@ -262,10 +265,6 @@ const TextInput = React.forwardRef( forceFocus: () => root.current?.focus(), })); - React.useLayoutEffect(() => { - if (typeof rest.value !== 'undefined') setValue(rest.value); - }, [rest.value]); - React.useEffect(() => { // When the input has an error, we wiggle the label and apply error styles if (errorProp) { @@ -376,7 +375,10 @@ const TextInput = React.forwardRef( return; } - setValue(value); + if (!isControlled) { + // Keep track of value in local state when input is not controlled + setUncontrolledValue(value); + } rest.onChangeText?.(value); };