Mastering Inactivity Logout in React Native
Tags: reactnative, javascript, android, ios
Published: 2024-01-21 18:50:58

Welcome to another exciting journey in React Native development! In this guide, we're going to explore a crucial feature for both security and user experience: inactivity logout. By the end of this post, you'll be equipped with the knowledge to implement a robust solution for your React Native applications.

## Setting Up the Basics:

Before we dive into the code, let's make sure we have the necessary tools. Install the **'moment'** library to help with time-related operations. Open your terminal and run:

```bash
npm install moment
```

## Tracking User Inactivity:

The first step is detecting user interactions. React Native provides the PanResponder API for handling touch events. Let's set up a PanResponder to track user activity:

```jsx
import { PanResponder } from 'react-native';

const MyApp = () => {
  // Initialize the PanResponder
  const panResponder = React.useRef(
    PanResponder.create({
      onStartShouldSetPanResponder: () => true,
      onMoveShouldSetPanResponder: () => true,
      onPanResponderTerminationRequest: () => false,
      onShouldBlockNativeResponder: () => false,
    })
  ).current;

  // ... rest of your component logic
};
```

## Implementing Inactivity Timeout:

With user activity being tracked, let's move on to implementing the inactivity timeout. We'll use moment to handle time calculations:

```jsx
import moment from 'moment';

// ... inside your component

const MyApp = () => {
  // Ref to store the timestamp of the last interaction
  const lastInteraction = React.useRef(new Date());
  // Ref to store the ID of the inactivity timer
  const inactivityTimer = React.useRef(null);
  // Set the time limit for inactivity logout (5 minutes)
  const IDLE_LOGOUT_TIME_LIMIT = 5 * 60 * 1000;

  // Function to check inactivity and trigger logout if needed
  const checkInactive = React.useCallback(() => {
    // Check if the inactivity timer is already running
    if (inactivityTimer.current) {
      return;
    }
    // Start the inactivity timer
    inactivityTimer.current = setInterval(() => {
      // Get the current time
      const currentTime = moment();
      // Calculate the elapsed time since the last interaction
      const elapsedTime = moment(currentTime).diff(lastInteraction.current);

      // Check if the elapsed time exceeds the defined time limit
      if (elapsedTime >= IDLE_LOGOUT_TIME_LIMIT) {
        // Trigger the function to handle inactivity logout
        setIsInactive();
      }
    }, 1000); // Check every second
  }, [setIsInactive]);

  React.useEffect(() => {
    // Initialize inactivity tracking when the component mounts
    checkInactive();
    // Cleanup function to clear the inactivity timer on component unmount
    return () => clearInterval(inactivityTimer.current);
  }, [checkInactive]);

  // ... rest of your component logic
};
```

## Handling App State Changes:

To ensure a seamless experience when the app goes into the background or returns to the foreground, let's handle app state changes:

```jsx
import { AppState } from 'react-native';

// ... inside your component

React.useEffect(() => {
  // Function to handle changes in app state (background/foreground)
  const handleAppStateChange = (nextAppState) => {
    // If the app is back in the foreground, reset the timeout
    if (nextAppState === 'active') {
      resetTimeout();
    }
  };

  // Subscribe to app state changes
  AppState.addEventListener('change', handleAppStateChange);

  // Cleanup function to remove the subscription when the component unmounts
  return () => {
    AppState.removeEventListener('change', handleAppStateChange);
  };
}, [resetTimeout]);
```

## Bonus Tip - Handling Keyboard Activity:

Consider scenarios where keyboard interactions might affect user activity. Reset the timeout when the keyboard is displayed or hidden:

```jsx
import { Keyboard } from 'react-native';

// ... inside your component

React.useEffect(() => {
  // Subscribe to keyboard show and hide events
  const keyboardShowSubscription = Keyboard.addListener(
    'keyboardDidShow',
    handleKeyboardActivity
  );
  const keyboardHideSubscription = Keyboard.addListener(
    'keyboardDidHide',
    handleKeyboardActivity
  );

  // Cleanup function to remove the subscriptions when the component unmounts
  return () => {
    keyboardShowSubscription.remove();
    keyboardHideSubscription.remove();
  };
}, [handleKeyboardActivity]);
```

Congratulations! You've successfully implemented inactivity logout in your React Native application. This not only enhances security by automatically logging out inactive users but also contributes to a smoother user experience. Feel free to customize the timings and adapt the code to fit your app's specific needs.

Happy coding! 🚀