There are times when you need to force the focus onto an element. In my case, I ran into an issue where a modal opened to give the user more information, but when the modal closed, the focus went back to the top of the screen instead of staying on the element. This is an accessibility concern.

Image for post

I’ll cover the solutions you might try to implement first (what would work in React), and then provide the React Native key to focusing an element for accessibility.


Attempt 1: useRef()

If you have a functional component, you might reach for useRef() like you would in React… However, you might be surprised when your attempt doesn’t work.

import React, { useRef } from 'react';

const EditableField = () => {

  const myElement = useRef();
  const onModalClose = () => {   
      myElement.current.focus();
  };
  return (
     <View>
      <TouchableOpacity
        accessible
        ref={myElement}
        onPress{() => {
          Alert.alert(
            'I am an alert',
            'Which tells you more information',
            [{ text: 'Okay', onPress: onModalClose }],
            { cancelable: true },
          );
        }}
      >
      Click Me!
      </TouchableOpacity>
   </View>
  )
};
};

Attempt 2: createRef

In my case, I had a large class component, so I reached for createRef. I wrote the code as I normally would for a React component. However, this approach wasn’t working.

import React, { createRef } from 'react';
import {  Alert, TouchableOpacity,  View } from 'react-native';

renderElement() {
  const myElement = createRef();
  const onModalClose = () => {
    if(myElement && myElement.current) {
        myElement.current.focus();
    }
  }
  return (
    <View>
      <TouchableOpacity
        accessible
        ref={myElement}
        onPress{() => {
          Alert.alert(
            'I am an alert',
            'Which tells you more information',
            [{ text: 'Okay', onPress: onModalClose }],
            { cancelable: true },
          );
        }}
      >
      Click Me!
      </TouchableOpacity>
   </View>
  )
};

The Key To The Solution for React Native

The key to the React Native solution are two elements:

findNodeHandle: obtains a native node handle for a component

AccessibilityInfo: Identifies whether or not the device has a screen reader that is currently active.

Using these two react-native elements, you can come up with something like this to grab the element and set the focus:

    const reactTag = findNodeHandle(myElement.current);
    if (reactTag) {
       AccessibilityInfo.setAccessibilityFocus(reactTag);
    }

Solution for Functional Components:

import React, { useRef } from 'react';
import {  Alert, TouchableOpacity,  View,  AccessibilityInfo,  findNodeHandle } from 'react-native';

const EditableField = () => {
  const myElement = useRef();
  const onModalClose = () => {   
    if(myElement && myElement.current) {
        const reactTag = findNodeHandle(myElement.current);
        if (reactTag) {
          AccessibilityInfo.setAccessibilityFocus(reactTag);
        }
     }  
  };
return (
     <View>
      <TouchableOpacity
        accessible
        ref={myElement}
        onPress{() => {
          Alert.alert(
            'I am an alert',
            'Which tells you more information',
            [{ text: 'Okay', onPress: onModalClose }],
            { cancelable: true },
          );
        }}
      >
      Click Me!
      </TouchableOpacity>
   </View>
  )
};

Solution for Class Components:

Although this approach might have worked in web, for React Native, there is a different way.

import React, { createRef } from 'react';
import {  Alert, TouchableOpacity,  View,  AccessibilityInfo,  findNodeHandle } from 'react-native';

renderElement() {
  const myElement = createRef();
  const onModalClose = () => {
    if(myElement && myElement.current){ // null check to satisfy TS
        const reactTag = findNodeHandle(myElement.current);
        if (reactTag) {
          AccessibilityInfo.setAccessibilityFocus(reactTag);
        }
     }
    }
  return (
    <View>
      <TouchableOpacity
        accessible
        ref={ myElement }
        onPress{() => {
          Alert.alert(
            'I am an alert',
            'Which tells you more information',
            [{ text: 'Okay', onPress: onModalClose }],
            { cancelable: true },
          );
        }}
      >
      Click Me!
      </TouchableOpacity>
   </View>
  )
};

#accessibility #code #software-development #mobile-app-development #react-native

Setting Focus For Accessibility In React Native
29.45 GEEK