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](e912c462eb/Libraries/Components/TextInput/TextInputState.js (L46)
) or rather [this one](1b2b2198e1/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: https://github.com/facebook/react-native/pull/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
This commit is contained in:
Родитель
83ab3615c5
Коммит
8a5460ce80
|
@ -73,7 +73,7 @@ function blurField(textFieldID: ?number) {
|
||||||
/**
|
/**
|
||||||
* @param {number} TextInputID id of the text field to focus
|
* @param {number} TextInputID id of the text field to focus
|
||||||
* Focuses the specified text field
|
* Focuses the specified text field
|
||||||
* noop if the text field was already focused
|
* noop if the text field was already focused or if the field is not editable
|
||||||
*/
|
*/
|
||||||
function focusTextInput(textField: ?ComponentRef) {
|
function focusTextInput(textField: ?ComponentRef) {
|
||||||
if (typeof textField === 'number') {
|
if (typeof textField === 'number') {
|
||||||
|
@ -86,7 +86,15 @@ function focusTextInput(textField: ?ComponentRef) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentlyFocusedInputRef !== textField && textField != null) {
|
if (textField != null) {
|
||||||
|
const fieldCanBeFocused =
|
||||||
|
currentlyFocusedInputRef !== textField &&
|
||||||
|
// $FlowFixMe - `currentProps` is missing in `NativeMethods`
|
||||||
|
textField.currentProps?.editable !== false;
|
||||||
|
|
||||||
|
if (!fieldCanBeFocused) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
focusInput(textField);
|
focusInput(textField);
|
||||||
if (Platform.OS === 'ios') {
|
if (Platform.OS === 'ios') {
|
||||||
// This isn't necessarily a single line text input
|
// This isn't necessarily a single line text input
|
||||||
|
|
|
@ -79,9 +79,26 @@ describe('TextInput tests', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have support being focused and unfocused', () => {
|
function createTextInput(extraProps) {
|
||||||
const textInputRef = React.createRef(null);
|
const textInputRef = React.createRef(null);
|
||||||
ReactTestRenderer.create(<TextInput ref={textInputRef} value="value1" />);
|
ReactTestRenderer.create(
|
||||||
|
<TextInput ref={textInputRef} value="value1" {...extraProps} />,
|
||||||
|
);
|
||||||
|
return textInputRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
it('focus() should not do anything if the TextInput is not editable', () => {
|
||||||
|
const textInputRef = createTextInput({editable: false});
|
||||||
|
// currentProps is the property actually containing props at runtime
|
||||||
|
textInputRef.current.currentProps = textInputRef.current.props;
|
||||||
|
expect(textInputRef.current.isFocused()).toBe(false);
|
||||||
|
|
||||||
|
TextInput.State.focusTextInput(textInputRef.current);
|
||||||
|
expect(textInputRef.current.isFocused()).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have support for being focused and blurred', () => {
|
||||||
|
const textInputRef = createTextInput();
|
||||||
|
|
||||||
expect(textInputRef.current.isFocused()).toBe(false);
|
expect(textInputRef.current.isFocused()).toBe(false);
|
||||||
ReactNative.findNodeHandle = jest.fn().mockImplementation(ref => {
|
ReactNative.findNodeHandle = jest.fn().mockImplementation(ref => {
|
||||||
|
|
Загрузка…
Ссылка в новой задаче