Focus not persisted on back navigation with nested Stack navigators

:warning: Before you continue


Before submitting a bug report, please review our troubleshooting documentation at Troubleshoot Issues | Vega Troubleshooting

If you still want to file a bug report, please make sure to fill in all the details below and provide the necessary information.

NOTE: PLEASE ONLY REPORT A SINGLE BUG USING THIS TEMPLATE.
If you’re experiencing multiple issues, please file a separate report for each.


:backhand_index_pointing_right: Bug Description


1. Summary

When using nested Stack navigators, the focus state is not correctly restored after back navigation in certain navigation paths. Specifically, the issue occurs when navigating between screens that span both the app-level and nested stacks.

App Name:
App Link on Amazon Appstore (found through Developer Console → Actions column in App List → View on Amazon.com):

Bug Severity
Select one that applies

  • Impacts operation of app
  • Blocks current development
  • Improvement suggestion
  • Issue with documentation (If selected, please share the doc link and describe the issue)
  • Other

2. Steps to Reproduce

  1. I have a minimal reproduction of the bug created on top of the vega’s hello-world template - Download code here, you can use this to reproduce the bug and can ignore the following points.
    One can also follow the below steps to reproduce it -
  2. Create vega hello-world app using - Build Your App | Design and Develop Vega Apps
  3. Add navigation by following - react-navigation | Vega Libraries, make sure to configure it the way described in the next steps.
  4. Create appStack at the root of the app by creating a stack navigator using createStackNavigator from @amazon-devices/react-navigation__stack and include three screens - DetailsScreen, PlayerScreen and Drawer.
  5. the Drawer screen should contain a nested stack navigator created using createStackNavigator, this navigator can again have few screens like HomeScreen. HomeScreen should be the initial route.
  6. In homeScreen - Create a grid of focusable components to mimic the screen with media cards. Wrap the grid inside TvFocusGuideView with autoFocus prop to persist the focus between navigations. The grid item should navigate the user to detailsScreen and details screen should have a way to navigate the user to the player screen.
  7. Test the following navigation flows -
    a. From HomeDetails → Back → Home → focus is correctly persisted.
    b. From HomeDetailsPlayer → Back → Details → Back → Home → focus is not persisted and it moves to the component with hasTvPreferredFocus
    c. From HomePlayer → Back → Home → focus is correctly persisted.

3. Observed Behavior

Explain what actually happened, noting any discrepancies or malfunctions.

Focus is lost when navigating back from deeper nested stack routes, for example - 
Nested Stack (Drawer screen) → Root Stack (Details) → Root Stack (Player Screen) → Back twice → focus not restored and moves to the first card of the grid (with hasTvPrefferedFocus true)

4. Expected Behavior

Describe what you expected the SDK to do under normal operation.

Focus should return to the previously focused element when navigating back, regardless of nesting depth.

4.a Possible Root Cause & Temporary Workaround

I could not find the root cause but one of the workaround i found was to remove the hasTvPrefferedFocus from the first component in the home-screen. But removing it is not feasible as it breaks the initial focus on the first card.

5. Logs or crash report

(Please make sure to provide relevant logs as attachment)

For crash issues, please refer this guide for faster troubleshooting: Detect Where the App Crash Originates | Design and Develop Vega Apps

  • App/Device Logs
  • Crash Logs
  • Crash Report
  • For issues with Kepler Studio Extension, please share log files from below folders:
     ~/.vscode/extensions/amazon.kepler-extension-<version>/ExtensionLogs
     ~/.vscode/extensions/amazon.kepler-ui-extension-<version>/ExtensionLogs
    

6. Environment

Please fill out the fields related to your bug below:

  • SDK Version: 0.21.4726
  • App State: Foreground
  • OS Information
    Please ssh into the device via kepler exec vda shelland copy the output from cat /etc/os-releaseinto the answer section below. Note, if you don’t have a simulator running or device attached kepler exec vda shell will respond with vda: no devices/emulators found
NAME="OS"
OE_VERSION="4.0.0"
OS_MAJOR_VERSION="1"
OS_MINOR_VERSION="1"
RELEASE_ID="10"
OS_VERSION="1.1"
BRANCH_CODE="TV Ship"
BUILD_DESC="OS 1.1 (TV Ship/4442)"
BUILD_FINGERPRINT="4.0.177029.0(3072cab629675a74)/4442N:user-external/release-keys"
BUILD_VARIANT="user-external"
BUILD_TAGS="release-keys"
BUILD_DATE="Fri Oct 31 16:11:40 UTC 2025"
BUILD_TIMESTAMP="1761927100"
VERSION_NUMBER="1001010444250"

7. Example Code Snippet / Screenshots / Screengrabs

Include any relevant code or component setup in React Native that can help reproduce the bug.

Reproduction - https://drive.google.com/file/d/1gxCzTd-GzWOZYaYhuUUN2xDYL8Tl6hsx/view?usp=drive_link
Screen record of the bug - https://drive.google.com/file/d/1Jt2RBEuXNKmyjyoTx0Uy98AoYLhe7zhd/view?usp=sharing


:backhand_index_pointing_right: Playback Issues


If this is a playback issue, please provide your content URL, any pre-conditions (like geo-location), and let us know if it’s x86 or arm7.


<!-- Describe your playback issue if applicable -->

Please share the following details in addition:_

  • Player SDK: [Bitmovin, Shaka, ...]
  • Player SDK Version: [e.g. 1.23]
    • Audio Codecs: [AAC, ...]
    • Video Codecs: [h.264, mp4]
    • Manifest Types: [m3u8, dash, etc ..]

Q: If applicable, please provide your media/content url
If this is created dynamically, tokenized, etc please provide a way for us to access it

[N/A or Content / Media Url for testing]

Q: Are there any special headers required to reproduce the issue you are facing?

[N/A or Insert Headers]

Additionally please provide the following if possible
Provide Screenshots / Screengrabs / Logs. Please include as much information as you can that will help debug.

<!-- Answer here if applicable --> 

:backhand_index_pointing_right: Additional Context


Any Additional Context you would like to provide?
Add any other relevant information, such as recent updates to the SDK, dependencies, or device OS that may affect the bug.

<!-- Answer here if applicable  --> 

Hi @Chandraprakash_Sutha

Thanks for sharing this issue, I looked into it and was able to reproduce the issue.
I was able to resolve it as well.

Instead of createStackNavigator in AppStack.tsx, I used createNativeStackNavigator and in the imports, I used
import {createNativeStackNavigator} from '@amazon-devices/react-native-screens/native-stack';

You’ll get more details on createNativeStackNavigator here.
This resolved the focus issue.

However, I had one more concern.
In HomeScreen.tsx you have used the following piece of code

    useCallback(() => {
      containerRef.current?.setNativeProps({hasTVPreferredFocus: true});
    }, []),
  );

But, in order to restore focus when a user navigates back to the top of the previous page by setting up a ref to keep track of the last focused item, by updating the reference when an item receives focus, and then by using the useFocusEffect() hook with FocusManager.focus() to restore focus.
In your shared code snippet, I was not able to find where you set up a ref to keep track of the last focused item, by updating the reference when an item receives focus.
Hence, sharing the below steps to restore focus.

1.To keep track of the last focused item on the page, set up a ref:

const lastFocusItemRef = React.useRef<TouchableOpacity | null>(null);

2.After an item receives focus, update the reference:

const FocusableView = memo(
forwardRef<TouchableOpacity, FocusableViewProps>((props, ref) => {
   const [focused, setFocused] = useState(false);
   const localRef = React.useRef<TouchableOpacity>(null);

   useImperativeHandle(ref, () => localRef.current!);

   const handleFocus = useCallback(
      (event: NativeSyntheticEvent<TargetedEvent>) => {
      props.onFocus?.(event);
      setFocused(true);
      props.onFocusedRefUpdate ?.(localRef);
      console.log("item focused");
      },
      [props],
   );

   ...
})
)

3.To restore focus when the previous page gets mounted, use the useFocusEffect() hook provided by React Navigation, and combine the hook with FocusManager.focus():

useFocusEffect(
    FocusManager.focus(findNodeHandle(focusedRef.current));
);

Hope this helps and using createNativeStackNavigator solves your issue.
Let me know if it works.

Warm regards,
Ivy

Hi @Ivy_Mahajan, thank you for the detailed explanation.
This approach should work but I believe its a workaround to the problem i reported and not a proper solution.
Persisting focus between navigations has been solved by react-native-tvos community by using TvFocusGuideView and its autoFocus prop. This also works with VEGA except for the case i have explained in my post.

The reason I did not implement the focus restore by storing the last focused item’s ref is that it requires to modify the common code that we have for the components which is being used across all the platforms and not just kepler, maintaining this solution across all that would not be feasible.
The approach that i am using is working well with other platforms as well as VEGA (except this issue), this is also recommended approach by the react-native-tvos community -

  1. [TVOS NEW ARCH] TVFocusGuideView with autofocus Prop Always Defaults to First Focusable Element with New Architecture on Screen Navigation · Issue #815 · react-native-tvos/react-native-tvos · GitHub
  2. [ANDROID TV] Focus gets lost between page transitions · Issue #1706 · software-mansion/react-native-screens · GitHub
    (FYI, these issues have been fixed and closed)

I will change the navigator to the one you recommended and see if it works fine or not. But i would request you to look into the problem and why navigation fails to persist the focus incase of nested navigators.

One more thing, it works fine with my setup if we dont use hasTvPreferredFocus on the screen. I am not sure why removing hasTvPreferredFocus works fine.
I have modified the code that i shared earlier to not have preferredFocus on home screen - Download here
You will have to press a d-pad key to focus an item after navigating to the home-screen as we dont have hasTvPrefferedFocus on any item but the focus will be persisted, you will see the previously focused item will focused again after pressing d-pad button.

I would have investigated further if the navigation libraries’ code was available.
Please let me know if you have any question.

Thanks,
Chandra

Thanks @Chandraprakash_Sutha , I’ll definitely be looking into this.

1 Like