diff --git a/src/components/TextInput/BaseTextInput.js b/src/components/TextInput/BaseTextInput.js index 1a6eec10fb7d..c17d8b173d11 100644 --- a/src/components/TextInput/BaseTextInput.js +++ b/src/components/TextInput/BaseTextInput.js @@ -37,6 +37,7 @@ class BaseTextInput extends Component { // Value should be kept in state for the autoGrow feature to work - https://github.com/Expensify/App/pull/8232#issuecomment-1077282006 value, + hiddenInputValue: value, }; this.input = null; @@ -67,13 +68,23 @@ class BaseTextInput extends Component { this.input.focus(); } - componentDidUpdate(prevProps) { + componentDidUpdate(prevProps, prevState) { // Activate or deactivate the label when value is changed programmatically from outside const inputValue = _.isUndefined(this.props.value) ? this.input.value : this.props.value; if ((_.isUndefined(inputValue) || this.state.value === inputValue) && _.isEqual(prevProps.selection, this.props.selection)) { return; } + if (this.props.autoGrow && this.props.shouldWaitWidthCalculation) { + if (inputValue !== this.state.hiddenInputValue) { + this.setState({hiddenInputValue: inputValue, selection: this.props.selection}); + } + + if (prevState.textInputWidth === this.state.textInputWidth) { + return; + } + } + // eslint-disable-next-line react/no-did-update-set-state this.setState({value: inputValue, selection: this.props.selection}); @@ -147,7 +158,9 @@ class BaseTextInput extends Component { if (this.props.onInputChange) { this.props.onInputChange(value); } - this.setState({value}); + if (!this.props.autoGrow || !this.props.shouldWaitWidthCalculation) { + this.setState({value}); + } Str.result(this.props.onChangeText, value); this.activateLabel(); } @@ -222,6 +235,8 @@ class BaseTextInput extends Component { {}, ); const isMultiline = this.props.multiline || this.props.autoGrowHeight; + const inputValue = this.state.value || this.props.placeholder; + const hiddenInputValue = this.state.hiddenInputValue || this.props.placeholder; return ( <> @@ -386,9 +401,14 @@ class BaseTextInput extends Component { styles.hiddenElementOutsideOfWindow, styles.visibilityHidden, ]} - onLayout={(e) => this.setState({textInputWidth: e.nativeEvent.layout.width + 2, textInputHeight: e.nativeEvent.layout.height})} + onLayout={(e) => + this.setState({textInputWidth: e.nativeEvent.layout.width + 2, textInputHeight: e.nativeEvent.layout.height}, () => { + if (!this.props.shouldWaitWidthCalculation) return; + this.setState((prevState) => ({value: prevState.hiddenInputValue, selection: this.props.selection})); + }) + } > - {this.state.value || this.props.placeholder} + {this.props.autoGrowHeight || !this.props.shouldWaitWidthCalculation ? inputValue : hiddenInputValue} )} diff --git a/src/components/TextInput/baseTextInputPropTypes.js b/src/components/TextInput/baseTextInputPropTypes.js index 45720ceb8c47..badc1685573c 100644 --- a/src/components/TextInput/baseTextInputPropTypes.js +++ b/src/components/TextInput/baseTextInputPropTypes.js @@ -85,6 +85,9 @@ const propTypes = { /** Set the default value to the input if there is a valid saved value */ shouldUseDefaultValue: PropTypes.bool, + + /** Indicate whether input should wait until getting calculated width based on value */ + shouldWaitWidthCalculation: PropTypes.bool, }; const defaultProps = { @@ -121,6 +124,7 @@ const defaultProps = { icon: null, shouldUseDefaultValue: false, multiline: false, + shouldWaitWidthCalculation: false, }; export {propTypes, defaultProps}; diff --git a/src/components/TextInput/index.js b/src/components/TextInput/index.js index d8ef3e7f1535..ad24340169fa 100644 --- a/src/components/TextInput/index.js +++ b/src/components/TextInput/index.js @@ -3,6 +3,7 @@ import _ from 'underscore'; import styles from '../../styles/styles'; import BaseTextInput from './BaseTextInput'; import * as baseTextInputPropTypes from './baseTextInputPropTypes'; +import * as BrowserUtils from '../../libs/Browser'; class TextInput extends React.Component { componentDidMount() { @@ -22,6 +23,7 @@ class TextInput extends React.Component { { this.textInput = el; if (!this.props.innerRef) {