DEV Community

Joseph Ajayi
Joseph Ajayi

Posted on

Session Management and Inactivity Detection in React Native: A Complete Guide

If you're building a fintech, healthcare, or enterprise React Native app, you've probably faced this question: How do I automatically log users out after they've been inactive?

It sounds simple. It isn't.

Why Session Timeout Matters

Regulatory frameworks like PCI-DSS, HIPAA, and SOC2 require automatic session termination after periods of inactivity. Beyond compliance, it's just good security—an unattended phone with an open banking app is a liability.

The requirements are straightforward:

  • Detect when a user stops interacting with the app
  • Show a warning before the session expires
  • Log them out if they don't respond
  • Handle edge cases like backgrounding, multitasking, and device sleep

The implementation? That's where it gets tricky.

The Manual Approach (And Why It's Painful)

Most teams start by rolling their own solution. It typically looks something like this:

const [lastActivity, setLastActivity] = useState(Date.now());

useEffect(() => {
  const interval = setInterval(() => {
    if (Date.now() - lastActivity > TIMEOUT_DURATION) {
      logout();
    }
  }, 1000);

  return () => clearInterval(interval);
}, [lastActivity]);
Enter fullscreen mode Exit fullscreen mode

Then you need to track activity. So you add touch handlers:

<View onTouchStart={() => setLastActivity(Date.now())}>
  <App />
</View>
Enter fullscreen mode Exit fullscreen mode

But wait—what about scrolling? Gestures? Keyboard input? Now you're wrapping components, adding PanResponders, and suddenly you have 300+ lines of session management code scattered across your app.

Then come the edge cases:

Android 10+ background restrictions — Your timer might not fire reliably when the app is backgrounded. Android aggressively kills background processes to save battery.

App state transitions — What happens when the user switches to another app and comes back? Should the timer pause? Continue? Reset?

Warning UI — You need a countdown dialog that updates every second, doesn't block interaction, and lets users extend their session.

Race conditions — If the warning and timeout fire at the same time, you might show a dialog after already logging the user out.

I've seen production apps with bugs in all of these areas.

A Better Approach

After dealing with this enough times, I built react-native-session-timeout to handle it properly.

The core idea is simple: wrap your app in a provider, configure your timeout, and let the library handle the rest.

import { SessionTimeoutProvider } from 'react-native-session-timeout';

function App() {
  return (
    <SessionTimeoutProvider
      timeout={300000} // 5 minutes
      warningDuration={60000} // 1 minute warning
      onTimeout={handleLogout}
      onWarning={(remaining) => console.log(`${remaining}ms left`)}
    >
      <YourApp />
    </SessionTimeoutProvider>
  );
}
Enter fullscreen mode Exit fullscreen mode

The library automatically detects all touch interactions—taps, scrolls, swipes, gestures—and resets the timer. No need to manually wire up event handlers throughout your app.

Building Custom Warning UI

The library doesn't force a specific warning dialog on you. Instead, it exposes a hook with the state you need:

import { useSessionTimeout } from 'react-native-session-timeout';

function SessionWarningBanner() {
  const { isWarning, remainingTime, resetTimer } = useSessionTimeout();

  if (!isWarning) return null;

  return (
    <View style={styles.banner}>
      <Text>
        Session expires in {Math.floor(remainingTime / 1000)}s
      </Text>
      <Button title="Stay logged in" onPress={resetTimer} />
    </View>
  );
}
Enter fullscreen mode Exit fullscreen mode

Want a modal instead? A full-screen overlay? A subtle toast? You have full control.

Handling Background State

One of the trickier decisions is what to do when the app is backgrounded. The pauseOnBackground prop gives you control:

<SessionTimeoutProvider
  timeout={300000}
  pauseOnBackground={true} // Timer pauses when app is in background
  onTimeout={handleLogout}
>
Enter fullscreen mode Exit fullscreen mode

For banking apps, you might want pauseOnBackground={false}—the session should expire even if the user switched to another app. For less sensitive apps, pausing might provide a better user experience.

Complete Implementation Example

Here's how a fintech app might implement this:

import React from 'react';
import { Modal, View, Text, Button, Alert } from 'react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { SessionTimeoutProvider, useSessionTimeout } from 'react-native-session-timeout';

function TimeoutWarningModal() {
  const { isWarning, remainingTime, resetTimer } = useSessionTimeout();

  return (
    <Modal visible={isWarning} transparent animationType="fade">
      <View style={styles.overlay}>
        <View style={styles.modal}>
          <Text style={styles.title}>Still there?</Text>
          <Text style={styles.message}>
            For your security, we'll log you out in{' '}
            {Math.floor(remainingTime / 1000)} seconds.
          </Text>
          <Button title="Continue Session" onPress={resetTimer} />
        </View>
      </View>
    </Modal>
  );
}

function App() {
  const handleTimeout = async () => {
    // Clear stored credentials
    await AsyncStorage.multiRemove(['authToken', 'refreshToken']);

    // Navigate to login
    navigation.reset({ index: 0, routes: [{ name: 'Login' }] });

    // Inform the user
    Alert.alert(
      'Session Expired',
      'You were logged out due to inactivity.'
    );
  };

  return (
    <SessionTimeoutProvider
      timeout={300000}
      warningDuration={60000}
      onTimeout={handleTimeout}
      pauseOnBackground={false}
    >
      <Navigation />
      <TimeoutWarningModal />
    </SessionTimeoutProvider>
  );
}
Enter fullscreen mode Exit fullscreen mode

Key Takeaways

  1. Don't underestimate the complexity — Manual session timeout handling involves more edge cases than it appears.

  2. Android 10+ needs special handling — Background timer restrictions are real and will bite you in production.

  3. Separate the timer logic from the UI — Let your session management handle the timing; build whatever warning UI fits your app.

  4. Consider your compliance requirements — PCI-DSS, HIPAA, and SOC2 all have specific requirements around session management.

If you're building a React Native app that needs session timeout, check out react-native-session-timeout. It's MIT licensed and handles the hard parts so you don't have to.


Have questions or feedback? Open an issue on GitHub.

Top comments (0)