@@ -131,6 +131,7 @@ export const reducer = (state: IState, action: IAction) => {
131131 }
132132
133133 case Type . SetFocus : {
134+ if ( state . activeRef === action . payload . ref ) return state ;
134135 // update active ref
135136 state . activeRef = action . payload . ref ;
136137 return { ...state } ;
@@ -194,6 +195,7 @@ export const RovingTabIndexProvider: React.FC<IProps> = ({
194195 }
195196
196197 let handled = false ;
198+ let focusRef : RefObject < HTMLElement > ;
197199 // Don't interfere with input default keydown behaviour
198200 if ( ev . target . tagName !== "INPUT" && ev . target . tagName !== "TEXTAREA" ) {
199201 // check if we actually have any items
@@ -202,15 +204,15 @@ export const RovingTabIndexProvider: React.FC<IProps> = ({
202204 if ( handleHomeEnd ) {
203205 handled = true ;
204206 // move focus to first (visible) item
205- findSiblingElement ( context . state . refs , 0 ) ?. current ?. focus ( ) ;
207+ focusRef = findSiblingElement ( context . state . refs , 0 ) ;
206208 }
207209 break ;
208210
209211 case Key . END :
210212 if ( handleHomeEnd ) {
211213 handled = true ;
212214 // move focus to last (visible) item
213- findSiblingElement ( context . state . refs , context . state . refs . length - 1 , true ) ?. current ?. focus ( ) ;
215+ focusRef = findSiblingElement ( context . state . refs , context . state . refs . length - 1 , true ) ;
214216 }
215217 break ;
216218
@@ -220,7 +222,7 @@ export const RovingTabIndexProvider: React.FC<IProps> = ({
220222 handled = true ;
221223 if ( context . state . refs . length > 0 ) {
222224 const idx = context . state . refs . indexOf ( context . state . activeRef ) ;
223- findSiblingElement ( context . state . refs , idx - 1 ) ?. current ?. focus ( ) ;
225+ focusRef = findSiblingElement ( context . state . refs , idx + 1 ) ;
224226 }
225227 }
226228 break ;
@@ -231,7 +233,7 @@ export const RovingTabIndexProvider: React.FC<IProps> = ({
231233 handled = true ;
232234 if ( context . state . refs . length > 0 ) {
233235 const idx = context . state . refs . indexOf ( context . state . activeRef ) ;
234- findSiblingElement ( context . state . refs , idx + 1 , true ) ?. current ?. focus ( ) ;
236+ focusRef = findSiblingElement ( context . state . refs , idx - 1 , true ) ;
235237 }
236238 }
237239 break ;
@@ -242,7 +244,17 @@ export const RovingTabIndexProvider: React.FC<IProps> = ({
242244 ev . preventDefault ( ) ;
243245 ev . stopPropagation ( ) ;
244246 }
245- } , [ context . state , onKeyDown , handleHomeEnd , handleUpDown , handleLeftRight ] ) ;
247+
248+ if ( focusRef ) {
249+ focusRef . current ?. focus ( ) ;
250+ dispatch ( {
251+ type : Type . SetFocus ,
252+ payload : {
253+ ref : focusRef ,
254+ } ,
255+ } ) ;
256+ }
257+ } , [ context , onKeyDown , handleHomeEnd , handleUpDown , handleLeftRight ] ) ;
246258
247259 return < RovingTabIndexContext . Provider value = { context } >
248260 { children ( { onKeyDownHandler } ) }
@@ -283,7 +295,7 @@ export const useRovingTabIndex = (inputRef?: Ref): [FocusHandler, boolean, Ref]
283295 type : Type . SetFocus ,
284296 payload : { ref } ,
285297 } ) ;
286- } , [ ref , context ] ) ;
298+ } , [ ] ) ; // eslint-disable-line react-hooks/exhaustive-deps
287299
288300 const isActive = context . state . activeRef === ref ;
289301 return [ onFocus , isActive , ref ] ;
0 commit comments