Spatial Navigation in React
Let’s face it! All the appliances around us are getting smarter. Especially our televisions! Gone are the times that you smacked your CRT tv to get it working. Nowadays all the major multimedia and entertainment companies have laid the foundation of groundbreaking “Smart Apps” for smarter TVs.
The problem with these “Smart Apps”, is that they should enhance a user’s experience of watching their favorite content, without essentially switching from the traditional way of using their remote control!
Now certainly, there are innovative products such as Touch panel enabled remotes, essentially transforming your remote into a trackpad for TV, but the core of this innovation remains the same, that is, intuitive switching between various screen items.
When a user presses the left directional key on their remote, the UI should show the left item to the current being in focus. When the user wants to scroll down, their down directional keypress should bring the next scrollable items in focus. This is the expected behavior and is thus an essential component of the overall architecture of the apps.
The Common Approach
Let’s assume our superstar frontend developer team is using the React library to achieve this functionality. Now there are several ways to achieve this via react!

- Distributed Navigation Logic: With this approach, we simply create a react state for each component and allow that component to contain and maintain the state of all the focusable items. However, this approach is not a feasible one as with this approach we can not achieve scalability. Allowing each component to maintain its own state would mean that in a large project we would need to poll and check the states of all the components to do anything. An example is shown below:
2. FocusMaps: The next approach is taking the focus logic and delegating it to the child components via object maps. Here we calculate the focus keys of elements that need to be focused along with their direction in an object before the element is focused. This object is calculated in the child components, thus, the parent components can simply render the children without the need to check the focus.
This approach takes a very opinionated turn as we have to define grids and structures for each and every child component. Only when we know for sure where an element is placed, can we accurately pinpoint the direction and focus keys for it, if it is focused. The problem here again lies in its scaling. Since we always need to follow a rigid structure, it restricts the way we define components in the long run and thus can not be used to define the focus for large projects.
The Modern Approach
Now that we have understood why traditional methods can not work for your next big app for smart televisions, we start looking for an approach that checks on all the following points:
- The logic to maintain a component’s focus should be abstracted away from the component itself.
- The component structure itself should not be opinionated and there should be ease of defining it.
- There should be a global way of maintaining where the focus currently is and which item was last focused.
- The parent, as well as child components, can be focused, so there should be a way to know what is currently being tracked.
- Finally, we must be able to debug the navigation logic to know which component will be available for focus next.
So considering all our key points in focus, let us take a look at an amazing spatial navigation open-source library by Norigin Media built specifically to address the growing need for smart TVs to navigate through their apps.
First things first. Here is the link to the library we will be talking about hereon to accomplish our goal of spatial navigation in React.

By using Norigin Media’s spatial navigation, we can not only accomplish all our key goals but also, in their own words, bring the best developer experience and performance when working with Spatial Navigation. When we talk about developer experience we want to accomplish the most abstraction of code, without compromising performance.
Now let us talk about how Norigin’s React Spatial Navigation library works. We will focus on Abstraction of Code, Inheritence and debugging our code.
Let’s begin by installing the React Spatial Navigation library to our react project. As is the case with any other NPM package, we can install this library with a simple command:
npm i @noriginmedia/react-spatial-navigation --save
This adds the required dependency for the react spatial navigation library in our react app.
Initializing our app
To initialize the React Spatial Navigation Library, we just have to follow two steps:
- Import the library in our project, preferably in App.js
- Initialise the library with the initNavigation() function
Understanding Code Abstraction
HOC is a technique used in React which allows us to reuse component logic due to react’s compositional nature. The distributed navigation logic involves a lot of repetition of managing states. To manage this, Norigin Media’s spatial navigation library introduces the HOC design of creating spatial navigation components.
As seen in the example above, we need to maintain a focused state and a way to identify which component is focused. This here is passed via the focused prop and the focusKey prop. Since we want to abstract the navigational logic, we also need a centralized navigational logic.
The HOC design allows us this abstraction, we don’t need to store any state logic within the component. This is further implemented via the spatial navigation service. On pressing any directional key, the algorithm finds the next closed child and brings that element/component to focus.

Here we can see that out of the possible selections, the closest neighbor to the first component would be the second component based on the calculation of distance between them.
There is a possibility that we may want to alter this logic so spatial navigation library also allows us to do that via the setFocus() method where we can pass the component to focus.
To update focus on the component, the spatial navigation library gets each component’s state handlers. This ensures that not all the components get updated altogether and only the states of two components are updated at a time. This improves performance and ensures that a cleaner logic is maintained.
Each component wrapped in spatial navigation HOC reports its own dimensions and coordinates which are used to further do navigation as well as do component manipulation.
The components can have two states:
1) Either they can be wrapped as a list of items, in which case, the spatial navigation, with the prop trackChildren set to true can set the focus on the items and not the parent container itself.
2) Or the focus can be set to be tracked just on the parent containers.
In the first approach, in a component like a scrollable list, once we reach the extreme of the list, the focus will again shift to the next closest component wrapped in the HOC.
Configuring Spatial Navigation Library
The next step after initialization would be to create a focussable HOC component.
We can do that as follows:
const FocusableRoot = withFocusable({
trackChildren: true,
})(Component);
The most commonly used props here are as follows:
- trackChildren
- onEnterPress
- onBecameFocused
- trackChildren: As the name states, the trackChildren prop allows us to track and pass down props to children of any parent focusable component. The children can further have the prop
hasFocusedChildwhich works similar to thefocusedprop and helps in setting different states of the component based on the focused prop being passed down.
- onEnterPress: The onEnterPress prop expects a function that allows handling events similar to onClick.
- onBecameFocused: The onBecameFocused callback doesn’t return any callback, but still has node ref to lazy measure the layout. It can calculate the coordinates, check the last focused child, or do a down tree propagation. It can contain the parameter of arguments that can help track the focused component’s dimensions.
Now let us take a look at the same example of a language picker being implemented via the spatial navigation library.
Let us first design the main App.js which will consist of a focusable root — to hold our components that need focus and other components.
Now let us create a list component for languages.
This will be a HOC component that serves the function of tracking children.
Finally, we create component of items.

Debug
To debug our spatial navigation, there can be two ways.
- To incorporate a debug at the console level which would allow us to check and test the focus keys, focus children, and which element will be focused on next nav.
- A visual debug that, would allow us to check the cues visually to see the currently focused element and the neighboring elements to be focused next.
This can be set as follows on the parent component, preferably app.js/focusable root:
initNavigation({ debug: true, visualDebug: true});
Conclusion
With the advent of smart televisions in the market, we can safely say that media entertainment has transformed into three major players now: the smartphone, the web, and the living room space which comprises not only smart TV’s but also other hardware such as smart set-top boxes, PlayStation, XBox, etc. With the knowledge of spatial navigation at our hand, we as devs can now step into this uncharted space and build user experiences that change the way people use their living room space!

Leave a Reply