mirror of
https://github.com/zoriya/react-native-web.git
synced 2026-06-06 03:45:18 +00:00
[fix] TextInput focus management
Defer to the browser's native handling of 'blur' and 'focus'; directly update the internal state of TextInputState. Fixes an issue with preserving focus when the tab is backgrounded. Also ensure the TextInputState is correctly set when a component mounts. When 'autoFocus' is true, 'onFocus' can be called before the internal ref is set. Fix #880
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
/* eslint-env jasmine, jest */
|
/* eslint-env jasmine, jest */
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import ReactDOM from 'react-dom';
|
||||||
import TextInput from '..';
|
import TextInput from '..';
|
||||||
import { mount, shallow } from 'enzyme';
|
import { mount, shallow } from 'enzyme';
|
||||||
|
|
||||||
@@ -112,8 +113,14 @@ describe('components/TextInput', () => {
|
|||||||
test('prop "onBlur"', () => {
|
test('prop "onBlur"', () => {
|
||||||
const onBlur = jest.fn();
|
const onBlur = jest.fn();
|
||||||
const input = findNativeInput(mount(<TextInput onBlur={onBlur} />));
|
const input = findNativeInput(mount(<TextInput onBlur={onBlur} />));
|
||||||
|
const node = ReactDOM.findDOMNode(input.instance());
|
||||||
|
|
||||||
|
// more accurate blur simulation
|
||||||
input.simulate('blur');
|
input.simulate('blur');
|
||||||
|
node.blur();
|
||||||
|
|
||||||
expect(onBlur).toHaveBeenCalledTimes(1);
|
expect(onBlur).toHaveBeenCalledTimes(1);
|
||||||
|
expect(TextInput.State.currentlyFocusedField()).toBe(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('prop "onChange"', () => {
|
test('prop "onChange"', () => {
|
||||||
@@ -135,8 +142,14 @@ describe('components/TextInput', () => {
|
|||||||
test('prop "onFocus"', () => {
|
test('prop "onFocus"', () => {
|
||||||
const onFocus = jest.fn();
|
const onFocus = jest.fn();
|
||||||
const input = findNativeInput(mount(<TextInput onFocus={onFocus} />));
|
const input = findNativeInput(mount(<TextInput onFocus={onFocus} />));
|
||||||
|
const node = ReactDOM.findDOMNode(input.instance());
|
||||||
|
|
||||||
|
// more accurate focus simulation
|
||||||
input.simulate('focus');
|
input.simulate('focus');
|
||||||
|
node.focus();
|
||||||
|
|
||||||
expect(onFocus).toHaveBeenCalledTimes(1);
|
expect(onFocus).toHaveBeenCalledTimes(1);
|
||||||
|
expect(TextInput.State.currentlyFocusedField()).toBe(node);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('prop "onKeyPress"', () => {
|
describe('prop "onKeyPress"', () => {
|
||||||
|
|||||||
@@ -161,6 +161,9 @@ class TextInput extends Component<*> {
|
|||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
setSelection(this._node, this.props.selection);
|
setSelection(this._node, this.props.selection);
|
||||||
|
if (document.activeElement === this._node) {
|
||||||
|
TextInputState._currentlyFocusedNode = this._node;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate() {
|
componentDidUpdate() {
|
||||||
@@ -263,7 +266,7 @@ class TextInput extends Component<*> {
|
|||||||
|
|
||||||
_handleBlur = e => {
|
_handleBlur = e => {
|
||||||
const { onBlur } = this.props;
|
const { onBlur } = this.props;
|
||||||
TextInputState.blurTextInput(this._node);
|
TextInputState._currentlyFocusedNode = null;
|
||||||
if (onBlur) {
|
if (onBlur) {
|
||||||
onBlur(e);
|
onBlur(e);
|
||||||
}
|
}
|
||||||
@@ -283,7 +286,7 @@ class TextInput extends Component<*> {
|
|||||||
_handleFocus = e => {
|
_handleFocus = e => {
|
||||||
const { clearTextOnFocus, onFocus, selectTextOnFocus } = this.props;
|
const { clearTextOnFocus, onFocus, selectTextOnFocus } = this.props;
|
||||||
const node = this._node;
|
const node = this._node;
|
||||||
TextInputState.focusTextInput(this._node);
|
TextInputState._currentlyFocusedNode = this._node;
|
||||||
if (onFocus) {
|
if (onFocus) {
|
||||||
onFocus(e);
|
onFocus(e);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user