Bohdan Yarema - Blog

React Native Activity Tracking

Hello and welcome!

Today we will look into activity tracking.
What do I mean by that?
Well, for some apps you might want to log the user out or at least lock the app till pin is entered if the user was inactive for a set period of time, say 10 minutes.

While there isn’t a universal solution to this there are a few simple ones that will work for a lot of applications.

Let’s begin with something simple. Let’s imagine an app, where it’s mostly just static screens or those that load the data once when they are open.
Well, we can then track navigation between those pages as an activity.
This isn’t perfect, as activities like scrolling through text or just tapping the screen randomly will not be registered.
But we’ll talk about more tricks soon. Have patience.

For this particular example I used react-navigation package for navigation.
It has a very useful event that we can use - navigation.addListener('state' => {}).
This triggers every time a navigation happens. And that includes navigation in nested navigators which is awesome!
However, this subscription must happen from within a navigator or a page inside root navigator.

Basically, if we have a root navigator like this

// ...
<Stack.Navigator>
    <Stack.Screen name="Home" component={HomeScreen} />
    <Stack.Screen name="Questionnaire" component={QuestionnaireNavigator} />
</Stack.Navigator>
// ...

then we need to subscribe in both HomeScreen and QuestionnaireNavigator. Note that if we are only tracking activity after login, then LoginNavigator should not have a subscription.

Let’s create a reusable hook to do that for us!

export default function useActivityTracking() {
    const navigation = useNavigation();
    useEffect(() => {
        const unsubscribe = navigation.addListener('state', () => {
            activityTracker.activity();
        });

        return unsubscribe;
    }, []);
}

activityTracker is a something that you will implement which will track the latest activity and do something on a timer. That I will leave up to you. You can use Redux, Mobx or plain react hooks like useContext for this. As an extra tip here - don’t call a setTimeout of 10 minutes because it will not work when the app is in the background. That is a limitation of RN. Rather do a setInterval which will every second check if 10 minutes have already passed since the last activity.

Let’s talk a bit about what we just wrote.
useEffect hook is used with the guard [] which means that it will only be called on initial render. Returning unsubscribe there means that it will unsubscribe when the screen or navigator is unmounted. Because it’s a good practise in software engineer to clean up after oneself. This way we can avoid unnecessary memory leaks.

Now, what about applications with a bit more dynamic screens with buttons and other interactions?
Well, we can still call our activityTracker.activity(). And if all actions trigger a request towards the server, then instead of doing it on every action you can just put this code into a service responsible for requests.

With these two tricks you can easily cover most scenarios.
Thank you for reading and I see you next time!