Skip to content

Commit 8a5460c

Browse files
vonovakfacebook-github-bot
authored andcommitted
fix attempting to focus disabled textinputs (#30695)
Summary: when we call `focus()` upon a TextInput ref which has prop `editable=false` it marks the textinput as focused in `TextInputState` even though the focus is rejected by textinput itself because it is not editable. then, when you change `editable` prop to `true` and call `focus` again, [this condition](https://github.com/facebook/react-native/blob/e912c462eb0b7166ca5947bb5a3ee20761d910b6/Libraries/Components/TextInput/TextInputState.js#L46) or rather [this one](https://github.com/facebook/react-native/blob/1b2b2198e1b2383523b4655dc8c220d251b057d6/Libraries/Components/TextInput/TextInputState.js#L89) will evaluate to `false` and focus will not happen even though it can and should happen. see also https://github.com/facebook/react-native/blob/0.64-stable/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js#L3895 ## Changelog <!-- Help reviewers and the release process by writing your own changelog entry. For an example, see: https://github.com/facebook/react-native/wiki/Changelog --> [General] [Fixed] - `focus()` on TextInput to respect its `editable` state Pull Request resolved: #30695 Test Plan: Create a `TextInput` with prop `editable=false` and call `ref.current.focus()` upon its ref. TextInput should not be marked as focused in `TextInputState`. Reviewed By: yungsters Differential Revision: D34357913 Pulled By: lunaleaps fbshipit-source-id: 9a2fb819bbb05ef213c9b5d739dec583ae0a3e6f
1 parent 83ab361 commit 8a5460c

File tree

2 files changed

+29
-4
lines changed

2 files changed

+29
-4
lines changed

Libraries/Components/TextInput/TextInputState.js

+10-2
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ function blurField(textFieldID: ?number) {
7373
/**
7474
* @param {number} TextInputID id of the text field to focus
7575
* Focuses the specified text field
76-
* noop if the text field was already focused
76+
* noop if the text field was already focused or if the field is not editable
7777
*/
7878
function focusTextInput(textField: ?ComponentRef) {
7979
if (typeof textField === 'number') {
@@ -86,7 +86,15 @@ function focusTextInput(textField: ?ComponentRef) {
8686
return;
8787
}
8888

89-
if (currentlyFocusedInputRef !== textField && textField != null) {
89+
if (textField != null) {
90+
const fieldCanBeFocused =
91+
currentlyFocusedInputRef !== textField &&
92+
// $FlowFixMe - `currentProps` is missing in `NativeMethods`
93+
textField.currentProps?.editable !== false;
94+
95+
if (!fieldCanBeFocused) {
96+
return;
97+
}
9098
focusInput(textField);
9199
if (Platform.OS === 'ios') {
92100
// This isn't necessarily a single line text input

Libraries/Components/TextInput/__tests__/TextInput-test.js

+19-2
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,26 @@ describe('TextInput tests', () => {
7979
});
8080
});
8181

82-
it('should have support being focused and unfocused', () => {
82+
function createTextInput(extraProps) {
8383
const textInputRef = React.createRef(null);
84-
ReactTestRenderer.create(<TextInput ref={textInputRef} value="value1" />);
84+
ReactTestRenderer.create(
85+
<TextInput ref={textInputRef} value="value1" {...extraProps} />,
86+
);
87+
return textInputRef;
88+
}
89+
90+
it('focus() should not do anything if the TextInput is not editable', () => {
91+
const textInputRef = createTextInput({editable: false});
92+
// currentProps is the property actually containing props at runtime
93+
textInputRef.current.currentProps = textInputRef.current.props;
94+
expect(textInputRef.current.isFocused()).toBe(false);
95+
96+
TextInput.State.focusTextInput(textInputRef.current);
97+
expect(textInputRef.current.isFocused()).toBe(false);
98+
});
99+
100+
it('should have support for being focused and blurred', () => {
101+
const textInputRef = createTextInput();
85102

86103
expect(textInputRef.current.isFocused()).toBe(false);
87104
ReactNative.findNodeHandle = jest.fn().mockImplementation(ref => {

0 commit comments

Comments
 (0)