11import { ForwardedRef , RefObject , useEffect , useImperativeHandle , useReducer , useRef } from 'react' ;
22import { Keyboard , NativeSyntheticEvent , Platform , TextInput , TextInputKeyPressEventData } from 'react-native' ;
33
4- import { useMemoizedFn , useSafeState } from '@td-design/rn-hooks' ;
4+ import { useMemoizedFn } from '@td-design/rn-hooks' ;
55
66import { fillOtpCode } from './helpers' ;
77import reducer from './reducer' ;
@@ -19,7 +19,6 @@ export default function usePasscode({
1919} ) {
2020 const previousCopiedText = useRef < string > ( '' ) ;
2121 const inputs = useRef < Array < RefObject < TextInput > > > ( [ ] ) ;
22- const [ index , setIndex ] = useSafeState ( 0 ) ;
2322
2423 const [ { otpCode, hasKeySupport } , dispatch ] = useReducer ( reducer , {
2524 otpCode : fillOtpCode ( count , value ) ,
@@ -36,13 +35,6 @@ export default function usePasscode({
3635 }
3736 } , [ value , count ] ) ;
3837
39- const fillInputs = useMemoizedFn ( ( code : string ) => {
40- dispatch ( {
41- type : 'setOtpCode' ,
42- payload : { count, code } ,
43- } ) ;
44- } ) ;
45-
4638 useImperativeHandle ( ref , ( ) => ( {
4739 reset : ( ) => {
4840 dispatch ( { type : 'clearOtp' , payload : count } ) ;
@@ -75,65 +67,58 @@ export default function usePasscode({
7567 text : '' ,
7668 } ,
7769 } ) ;
78- focusInput ( inputIndex - 1 ) ;
70+ } ;
71+
72+ const handleChangeText = ( index : number ) => ( text : string ) => {
73+ handleInputTextChange ( text , index ) ;
7974 } ;
8075
8176 const handleKeyPress =
8277 ( index : number ) =>
8378 ( { nativeEvent : { key } } : NativeSyntheticEvent < TextInputKeyPressEventData > ) => {
84- const text = key === 'Backspace' || key . length > 1 ? '' : key ;
85- handleInputTextChange ( text , index ) ;
86-
87- if ( Platform . OS === 'android' && ! hasKeySupport && ! isNaN ( parseInt ( key ) ) )
79+ if ( Platform . OS === 'android' && ! hasKeySupport && ! isNaN ( parseInt ( key ) ) ) {
8880 dispatch ( { type : 'setHasKeySupport' , payload : true } ) ;
81+ }
82+
83+ if ( key === 'Backspace' ) {
84+ // 当前输入框的值
85+ const value = otpCode [ `${ index } ` ] ;
86+ // 清除当前输入框的值
87+ handleClearInput ( index ) ;
88+ // 如果当前输入框的值为空,则聚焦上一个输入框
89+ if ( ! value ) {
90+ focusInput ( index - 1 ) ;
91+ }
92+ }
8993 } ;
9094
91- const handleTextChange = ( index : number ) => ( text : string ) => {
92- if (
93- ( Platform . OS === 'android' && ! hasKeySupport ) ||
94- // Pasted from input accessory
95- ( Platform . OS === 'ios' && text . length > 1 )
96- ) {
97- handleInputTextChange ( text , index ) ;
98- }
99- } ;
100-
10195 const handleInputTextChange = ( text : string , index : number ) : void => {
102- setIndex ( index ) ;
103-
104- if ( ! text . length ) {
105- handleClearInput ( index ) ;
106- }
107-
108- if ( text . length > 1 ) {
109- handleClearInput ( index ) ;
110- Keyboard . dismiss ( ) ;
111- return fillInputs ( text ) ;
112- }
113-
114- if ( text ) {
96+ if ( [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 0 ] . includes ( parseInt ( text ) ) ) {
11597 dispatch ( {
11698 type : 'setOtpTextForIndex' ,
11799 payload : {
118100 text,
119101 index,
120102 } ,
121103 } ) ;
104+ focusInput ( index + 1 ) ;
105+ } else {
106+ handleClearInput ( index ) ;
122107 }
123- focusInput ( index + 1 ) ;
124108 } ;
125109
126110 useEffect ( ( ) => {
127- if ( index === count - 1 ) {
128- onFinish ?.( ) ;
111+ const value = Object . values ( otpCode ) . join ( '' ) ;
112+ if ( value . length === count ) {
113+ onFinish ?.( value ) ;
129114 Keyboard . dismiss ( ) ;
130115 }
131- } , [ index , count ] ) ;
116+ } , [ count , otpCode ] ) ;
132117
133118 return {
134119 otpCode,
135120 inputs,
136121 handleKeyPress : useMemoizedFn ( handleKeyPress ) ,
137- handleTextChange : useMemoizedFn ( handleTextChange ) ,
122+ handleChangeText : useMemoizedFn ( handleChangeText ) ,
138123 } ;
139124}
0 commit comments