DEV Community

gie3d
gie3d

Posted on

Detect user idle in react-native

One of requirements in an app with sensitive data is to force user to logout if the user has been idle for certain amount of time. By idle, I mean the user doesn't touch anything in the app. Normally, we use Touchable* to detect a user press event. But we cannot apply this on top of another element because it will override all touch event on the pages and your app won't be functional. After a brief research, I found that we can use PanResponder.

My strategy is to apply PanResponser on top of the app. We start a setTimeout with a certain amount of time (supposed to be configurable) during the user opens the app. Whenever the user presses anywhere on the screen, we clearTimeout and reset it. Note that I used onStartShouldSetPanResponderCapture of PanResponser event to detect user touch event.

import React, { useState, useEffect, useRef } from "react"
import { View, PanResponder } from "react-native"

const AppContainer = props => {
  const timerId = useRef(false)
  const [timeForInactivityInSecond, setTimeForInactivityInSecond] = useState(
    3600
  )

  useEffect(() => {
    resetInactivityTimeout()
  }, [])

  const panResponder = React.useRef(
    PanResponder.create({
      onStartShouldSetPanResponderCapture: () => {
        // console.log('user starts touch');
        resetInactivityTimeout()
      },
    })
  ).current

  const resetInactivityTimeout = () => {
    clearTimeout(timerId.current)
    timerId.current = setTimeout(() => {
      // action after user has been detected idle
    }, timeForInactivityInSecond * 1000)
  }

  return (
    <View style={{ flex: 1 }} {...panResponder.panHandlers}>
      {/* <YourApp {...props} /> */}
    </View>
  )
}

export default AppContainer
Enter fullscreen mode Exit fullscreen mode

Latest comments (7)

Collapse
 
berkaygurcan profile image
Berkay Gürcan

Perfect solution! thank you

Collapse
 
codeby profile image
code-by

will not reset timer when user input text in TextInput

Collapse
 
andresrechimon profile image
Rechimon, Andrés. • Edited

Its done like you instructed. What is missing?
Image description

Collapse
 
gie3d profile image
gie3d

I'm not quite sure. What is an error shown if you mouse over those error lines

Collapse
 
jai_j_d4132b0c7fcd6b196ac profile image
Jai J

Type '() => void' is not assignable to type '(e: GestureResponderEvent, gestureState: PanResponderGestureState) => boolean'.
Type 'void' is not assignable to type 'boolean'.
This is the error it is showing

Collapse
 
elechipro profile image
Elechi George

If i wish to logout a user, where do i dispatch such action say am using redux dispatcher
?

Collapse
 
gie3d profile image
gie3d • Edited

I think you could do that in

const resetInactivityTimeout = () => {
    clearTimeout(timerId.current)
    timerId.current = setTimeout(() => {

      // action after user has been detected idle
      // add your redux dispatch here**

    }, timeForInactivityInSecond * 1000)
  }
Enter fullscreen mode Exit fullscreen mode