Become a member
to unlock all features

Level Up!

Access all courses & lessons on egghead today and lock-in your price for life.


    How to use a PanResponder to Detect Touch Inactivity in React Native

    react-nativeReact Native

    In this lesson we'll use PanResponder to create a component that tracks touch inactivity. We'll take advantage of the onMoveShouldSetPanResponderCapture function call of PanResponder to register touches when they happen but not steal touches from other elements.



    Become a Member to view code

    You must be a Pro Member to view code

    Access all courses and lessons, track your progress, gain confidence and expertise.

    Become a Member
    and unlock code for this lesson
    orLog In




    Instructor: There are times when you need to detect inactivity within your application and we can use the PanResponder to accomplish that. We need to first set up a componentWillMount and then we need to create our PanResponder. We'll assign to this.panResponder equals PanResponder.create, and there will be an object inside of that function call.

    There are many methods that PanResponder has but the one that we care about is the onMoveShouldSetPanResponderCapture method. What this method does is as a touch is handled on whatever element that we apply it to, the PanResponder will traverse its way down from view to view to few asking this Capture method if it needs to do anything. It will then bubble its way back up.

    The onTheCapture phase is just like the Web. However, we don't want to actually steal any touches. If we return true here, it would steal the touches as we traverse down and nothing inside of our container would be able to be captured or touched. However, if we return false, we can still do things inside of here, but we will always return false and therefore not steal any touches.

    Now that we have this in place, we need to set up some state. We'll say state equals inactive, true, so we'll start out in an inactive state. Then if we say this.setState inactive, false whenever anything is pressed, we will toggle our setState to false, which will trigger a re-render here and still not steal any of the touches.

    Now we need to set a threshold for our inactivity and we can do that with setTimeout. Inside of our setTimeout, we'll give it a duration. We'll pick an arbitrary one like 3,000-milliseconds, so 3 seconds. Then we'll say we are back to inactive. We'll say this.setTimeout, or setState, I should say, and say inactive, true.

    We can see this in action. We'll set up our text and say this.state.inactive. We'll just add a string to it to coerce it to a string, so it ought to be true or false. Then inside of our styles here, we can apply some styles that have already set up.

    When it's active, it will be back onto the tomato, when it's inactive, it will be black. We can use a ternary, say this.state.inactive. If it's inactive, we say styles.inactive, or if it's active then it would be styles.active.

    Finally, before this actually works, we need to attach our PanResponder to the view that we want to have touch inactivity on. We'll apply a spread.panHandlers. When we touch this, we can see that it changed to false, aka, it's active. Touch it again after three seconds, it will switch back to being inactive.

    Technically, this works. However, we need to add some protections in our code so that setState does not get called all the time constantly because that would cause our app to be re-rendered. This function is getting called every time we move and create a new gesture, which means this.setState will be called constantly. We don't want that to happen.

    To do this, we can use the setState with a function. We are referencing previous states, so we need to do this to be async safe. If state.inactive is equal to false already then we can just return null, and this instructs React that it does not need to do anything. Otherwise, we'll return inactive, false, and that way, we register our inactive false touch.

    Finally, the other thing that we need to do is clean our time out whenever this is touched. Because we'll be calling this every single time, this setTimeout will set multiple times and there will be a cascade every few milliseconds of a new setState.

    Here we'll need to save this off to this.timeout. Then anytime that this is touched, we'll just call clearTimeout, this.timeout. That way, every time we touch it, it's clearing the Timeout. Then we release and wait three seconds, and a final Timeout will execute and set inactive to true again.

    Finally, because we are doing a setState inside of a Timeout, if this component were to unmount for whatever reason, we would also want to clear our Timeouts. We're going to say componentWillUnmount, and say clearTimeout, this.timeout, just to be safe.