1
- import React from 'react' ;
1
+ import React , { useEffect , useRef } from 'react' ;
2
2
import _ from 'underscore' ;
3
3
import styles from '../../styles/styles' ;
4
4
import * as styleConst from './styleConst' ;
@@ -7,65 +7,66 @@ import * as baseTextInputPropTypes from './baseTextInputPropTypes';
7
7
import DomUtils from '../../libs/DomUtils' ;
8
8
import Visibility from '../../libs/Visibility' ;
9
9
10
- class TextInput extends React . Component {
11
- componentDidMount ( ) {
12
- if ( this . props . disableKeyboard ) {
13
- this . textInput . setAttribute ( 'inputmode' , 'none' ) ;
10
+ function TextInput ( props ) {
11
+ const textInputRef = useRef ( null ) ;
12
+ const removeVisibilityListenerRef = useRef ( null ) ;
13
+
14
+ useEffect ( ( ) => {
15
+ if ( props . disableKeyboard ) {
16
+ textInputRef . current . setAttribute ( 'inputmode' , 'none' ) ;
14
17
}
15
18
16
- if ( this . props . name ) {
17
- this . textInput . setAttribute ( 'name' , this . props . name ) ;
19
+ if ( props . name ) {
20
+ textInputRef . current . setAttribute ( 'name' , props . name ) ;
18
21
}
19
22
20
- // Forcefully activate the soft keyboard when the user switches between tabs while input was focused.
21
- this . removeVisibilityListener = Visibility . onVisibilityChange ( ( ) => {
22
- if ( ! Visibility . isVisible ( ) || ! this . textInput || DomUtils . getActiveElement ( ) !== this . textInput ) {
23
+ removeVisibilityListenerRef . current = Visibility . onVisibilityChange ( ( ) => {
24
+ if ( ! Visibility . isVisible ( ) || ! textInputRef . current || DomUtils . getActiveElement ( ) !== textInputRef . current ) {
23
25
return ;
24
26
}
25
- this . textInput . blur ( ) ;
26
- this . textInput . focus ( ) ;
27
+ textInputRef . current . blur ( ) ;
28
+ textInputRef . current . focus ( ) ;
27
29
} ) ;
28
- }
29
-
30
- componentWillUnmount ( ) {
31
- if ( ! this . removeVisibilityListener ) {
32
- return ;
33
- }
34
- this . removeVisibilityListener ( ) ;
35
- }
36
30
37
- render ( ) {
38
- const isLabeledMultiline = Boolean ( this . props . label . length ) && this . props . multiline ;
39
- const labelAnimationStyle = {
40
- '--active-label-translate-y' : `${ styleConst . ACTIVE_LABEL_TRANSLATE_Y } px` ,
41
- '--active-label-scale' : `${ styleConst . ACTIVE_LABEL_SCALE } ` ,
42
- '--label-transition-duration' : `${ styleConst . LABEL_ANIMATION_DURATION } ms` ,
31
+ return ( ) => {
32
+ if ( ! removeVisibilityListenerRef . current ) return ;
33
+ removeVisibilityListenerRef . current ( ) ;
43
34
} ;
35
+ // eslint-disable-next-line react-hooks/exhaustive-deps
36
+ } , [ ] ) ;
37
+
38
+ const isLabeledMultiline = Boolean ( props . label . length ) && props . multiline ;
39
+ const labelAnimationStyle = {
40
+ '--active-label-translate-y' : `${ styleConst . ACTIVE_LABEL_TRANSLATE_Y } px` ,
41
+ '--active-label-scale' : `${ styleConst . ACTIVE_LABEL_SCALE } ` ,
42
+ '--label-transition-duration' : `${ styleConst . LABEL_ANIMATION_DURATION } ms` ,
43
+ } ;
44
44
45
- return (
46
- < BaseTextInput
47
- // eslint-disable-next-line react/jsx-props-no-spreading
48
- { ... this . props }
49
- innerRef = { ( el ) => {
50
- this . textInput = el ;
51
- if ( ! this . props . innerRef ) {
52
- return ;
53
- }
45
+ return (
46
+ < BaseTextInput
47
+ // eslint-disable-next-line react/jsx-props-no-spreading
48
+ { ...props }
49
+ innerRef = { ( el ) => {
50
+ textInputRef . current = el ;
51
+ if ( ! props . innerRef ) {
52
+ return ;
53
+ }
54
54
55
- if ( _ . isFunction ( this . props . innerRef ) ) {
56
- this . props . innerRef ( el ) ;
57
- return ;
58
- }
55
+ if ( _ . isFunction ( props . innerRef ) ) {
56
+ props . innerRef ( el ) ;
57
+ return ;
58
+ }
59
59
60
- this . props . innerRef . current = el ;
61
- } }
62
- inputStyle = { [ styles . baseTextInput , styles . textInputDesktop , isLabeledMultiline ? styles . textInputMultiline : { } , ... this . props . inputStyle ] }
63
- textInputContainerStyles = { [ labelAnimationStyle , ...this . props . textInputContainerStyles ] }
64
- />
65
- ) ;
66
- }
60
+ // eslint-disable-next-line no-param-reassign
61
+ props . innerRef . current = el ;
62
+ } }
63
+ inputStyle = { [ styles . baseTextInput , styles . textInputDesktop , isLabeledMultiline ? styles . textInputMultiline : { } , ...props . inputStyle ] }
64
+ textInputContainerStyles = { [ labelAnimationStyle , ... props . textInputContainerStyles ] }
65
+ />
66
+ ) ;
67
67
}
68
68
69
+ TextInput . displayName = 'TextInput' ;
69
70
TextInput . propTypes = baseTextInputPropTypes . propTypes ;
70
71
TextInput . defaultProps = baseTextInputPropTypes . defaultProps ;
71
72
0 commit comments