<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Ryan Munsch</title>
    <description>The latest articles on Forem by Ryan Munsch (@rmunschie92).</description>
    <link>https://forem.com/rmunschie92</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F77414%2Fc110e2a5-c02f-4698-9625-14619687abd5.JPG</url>
      <title>Forem: Ryan Munsch</title>
      <link>https://forem.com/rmunschie92</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/rmunschie92"/>
    <language>en</language>
    <item>
      <title>Making an Input Slider in React Native with the Animated and Panresponder APIs</title>
      <dc:creator>Ryan Munsch</dc:creator>
      <pubDate>Thu, 03 Dec 2020 18:55:26 +0000</pubDate>
      <link>https://forem.com/rmunschie92/making-an-input-slider-in-react-native-with-the-animated-and-panresponder-apis-55pe</link>
      <guid>https://forem.com/rmunschie92/making-an-input-slider-in-react-native-with-the-animated-and-panresponder-apis-55pe</guid>
      <description>&lt;p&gt;This is the second of a two-part series on the React Native PanResponder API. See the first part &lt;a href="https://dev.to/rmunschie92/building-a-movable-animated-component-in-react-native-4o96"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now that we have a draggable component, let’s update our logic to give it the desired “slider” input behavior. The first step here is quite simple, we simply want to disable the &lt;code&gt;y&lt;/code&gt; value from being updated when we move the Animated View component. To do this we’ll go into our &lt;code&gt;onPanResponderMove&lt;/code&gt; handler and update the &lt;code&gt;y&lt;/code&gt; value to &lt;code&gt;0&lt;/code&gt; in &lt;code&gt;this.state.animate.setValue()&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// The user is moving their finger&lt;/span&gt;
&lt;span class="nx"&gt;onPanResponderMove&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;gesture&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Set value of state.animate x to the delta for x and y to 0&lt;/span&gt;
  &lt;span class="c1"&gt;// to prevent vertical movement&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;animate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;gesture&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With these changes made, refresh your simulator and try to move the component around the screen. Now you should be able to move it from along the screen’s x-axis, but any vertical movement should be disabled.&lt;/p&gt;

&lt;p&gt;Next, let’s include styles for a basic slider. Back in &lt;code&gt;Container.js&lt;/code&gt;, start by wrapping the instance of &lt;code&gt;&amp;lt;Movable /&amp;gt;&lt;/code&gt; in a &lt;code&gt;View&lt;/code&gt; component. Let’s give our new &lt;code&gt;View&lt;/code&gt; some basic styles to make it actually look something like an HTML range-type input; for now just a set width and height, a border, a border radius, and justify the &lt;code&gt;View&lt;/code&gt; content along the component’s center.&lt;/p&gt;

&lt;p&gt;Your Container component should now look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Container&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ScrollView&lt;/span&gt; &lt;span class="nx"&gt;contentContainerStyle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;container&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;canCancelContentTouches&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;                    
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;View&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slider&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Movable&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/View&amp;gt;  &lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ScrollView&amp;gt; &lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;    &lt;span class="p"&gt;);&lt;/span&gt; 
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; 

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;styles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;StyleSheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;container&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;vh&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#fff&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;alignItems&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;center&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;justifyContent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;center&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;slider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;vh&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1.5&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;vw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;85&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;borderWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;borderRadius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;justifyContent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;center&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Things should be &lt;em&gt;looking&lt;/em&gt; pretty good by now, but there’s an issue - nothing stops the user from simply dragging &lt;code&gt;&amp;lt;Movable /&amp;gt;&lt;/code&gt; right outside the horizontal boundaries of the  component acting as the slider itself.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fmunsch-creative%2Fimage%2Fupload%2Fv1607021251%2Fslider-no-min_max-offset_zhyudw.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fmunsch-creative%2Fimage%2Fupload%2Fv1607021251%2Fslider-no-min_max-offset_zhyudw.gif" alt="Slider with no min/max offset"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we’ll have to establish logic to keep &lt;code&gt;&amp;lt;Movable /&amp;gt;&lt;/code&gt; within the bounds of its parent component. Since we set the width of the slider component as 85% of the viewport width, we can bet that is going to be the maximum value we can drag &lt;code&gt;&amp;lt;Movable /&amp;gt;&lt;/code&gt; to along the x-axis. To get access to the maximum offset we want, pass &lt;code&gt;maxOffset&lt;/code&gt; as a prop to &lt;code&gt;&amp;lt;Movable /&amp;gt;&lt;/code&gt;; in this case we’ll pass &lt;code&gt;vw(85)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Before we move on, the value of &lt;code&gt;props.maxOffset&lt;/code&gt; will need to take the width of &lt;code&gt;&amp;lt;Movable /&amp;gt;&lt;/code&gt; into account, otherwise our positioning will be off by the value of the component's radius. We'll store the radius value in a class property, &lt;code&gt;this.componentRadius&lt;/code&gt;. Simply set the value to half of the component's width.&lt;/p&gt;

&lt;p&gt;We'll also set another class property, &lt;code&gt;this.initialPosition&lt;/code&gt;, the negation of &lt;code&gt;this.componentRadius&lt;/code&gt;. We'll use this value in a bit.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Get radius from StyleSheet rule&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;componentRadius&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;movable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// Set initial position to negative value of component's radius&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;initialPosition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;componentRadius&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// Set property maxOffset to prop value minus component's radius&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;maxOffset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;maxOffset&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;componentRadius&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;[...]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the value of &lt;code&gt;props.maxOffset&lt;/code&gt; in our Animated component, we'll have to incorporate the logic to actually limit movement beyond the bounds of the slider parent component. The logic for this is pretty straightforward, we need to get the &lt;code&gt;x&lt;/code&gt; offset of the component while it's being moved, and if it's less than  &lt;code&gt;0&lt;/code&gt; or is greater than &lt;code&gt;this.maxOffset&lt;/code&gt;, we don't want to allow the "movement", that is, the &lt;code&gt;setValue()&lt;/code&gt; called on the instance of &lt;code&gt;this.state.animate&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The tricky part of implementing this is actually getting the &lt;code&gt;x&lt;/code&gt; offset the user has dragged to. I calculated this by getting the sum of the change in the x offset and the most recent position of &lt;code&gt;&amp;lt;Movable /&amp;gt;&lt;/code&gt;. Let’s start by adding new value in state, &lt;code&gt;latestPosition&lt;/code&gt;. This will keep track of the latest position of the component along the x-axis. We’ll need this value to determine if the component is still within bounds of its parent when it is being moved. We'll intialize it as the value of &lt;code&gt;this.intialPosition&lt;/code&gt;, to account for the width of the component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Initialize state&lt;/span&gt;
&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Create instance of Animated.XY, which interpolates X and Y values&lt;/span&gt;
  &lt;span class="na"&gt;animate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ValueXY&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;latestPosition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;initialPosition&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We'll also need to update the &lt;code&gt;x&lt;/code&gt; value that we pass in &lt;code&gt;this.state.animate.setValue()&lt;/code&gt; for the same reason - we need to consider the width of the component skewing the positioning of &lt;code&gt;&amp;lt;Movable /&amp;gt;&lt;/code&gt; within the slider. We'll simply subtract the value of &lt;code&gt;this.componentRadius&lt;/code&gt; from the existing value of &lt;code&gt;0&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Initialize value of x and y coordinates&lt;/span&gt;
&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;animate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; 
    &lt;span class="c1"&gt;// Subtract half of the width of the component to account for positioning&lt;/span&gt;
    &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;componentRadius&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With our new state value and class properties in place, let's go back to &lt;code&gt;onPanResponderMove()&lt;/code&gt; and update the logic to perform what was described above to prevent movement out of bounds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// The user is moving their finger&lt;/span&gt;
&lt;span class="nx"&gt;onPanResponderMove&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;gesture&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Get the final value that user has dragged to.&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;finalOffset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;gesture&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dx&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;latestPosition&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// If finalOffset is within bounds of the slider, update state.drag to appropriate position&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;finalOffset&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;finalOffset&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;maxOffset&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;animate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;gesture&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now try saving, refreshing and moving the component around again. You'll see that the behavior is not there yet. We'll have to update the value of &lt;code&gt;this.state.latestPosition&lt;/code&gt; at the end of the touch event. In order to do so, we'll have to update &lt;code&gt;onPanResponderRelease()&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;At this point, your code should simply have a call to &lt;code&gt;this.state.animate.flattenOffset()&lt;/code&gt; in &lt;code&gt;onPanResponderRelease()&lt;/code&gt;. Since we're about to make the logic progressively more involved, I'd recommend moving the business logic into a handler function and passing it as a callback. Don't forget to update the handler in &lt;code&gt;PanResponder.create()&lt;/code&gt; to execute our callback and pass the gesture object as an argument.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Fired at the end of the touch&lt;/span&gt;
&lt;span class="nx"&gt;onPanResponderRelease&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;gesture&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;panResponderReleaseHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gesture&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;[...]&lt;/span&gt;

&lt;span class="cm"&gt;/** 
 * Event handler for when panResponder touch event ends. 
 * @param {Object} gesture - The gestureState object passed as a param to each panResponder callback.
 * @return {null} Updates local state.
*/&lt;/span&gt;
&lt;span class="nx"&gt;panResponderReleaseHandler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gesture&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Merges the offset value into the base value and resets the offset to     &lt;/span&gt;
  &lt;span class="c1"&gt;// zero&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;animate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;flattenOffset&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At the top of the function we’ll declare the &lt;code&gt;finalOffset&lt;/code&gt; variable the same way we did in &lt;code&gt;onPanResponderMove()&lt;/code&gt;. We'll also keep the call to &lt;code&gt;flattenOffset()&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Get the final x value that user has dragged to&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;finalOffset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;gesture&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dx&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;latestPosition&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Merges the offset value into the base value and resets the offset to&lt;/span&gt;
&lt;span class="c1"&gt;// zero&lt;/span&gt;
&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;animate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;flattenOffset&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Try &lt;code&gt;console.log()&lt;/code&gt;-ing the value of &lt;code&gt;finalOffset&lt;/code&gt; in the same handler function. If you refresh the simulator and drag the component roughly halfway to the other end of the slider, you should get a positive value (I got about &lt;code&gt;150&lt;/code&gt; on the simulated iPhone 11 Pro Max with after passing &lt;code&gt;vw(85)&lt;/code&gt; to &lt;code&gt;props.maxOffset&lt;/code&gt; .&lt;/p&gt;

&lt;p&gt;Before we go any further, we’re also going to need two more variables: one to eventually set as the &lt;code&gt;x&lt;/code&gt; value in &lt;code&gt;this.state.animate.setValue()&lt;/code&gt; , and a second to set as the updated value of &lt;code&gt;this.state.latestPosition&lt;/code&gt;. Let's call these &lt;code&gt;updatedOffsetX&lt;/code&gt; and &lt;code&gt;newPosition&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Initialize value we'll use to update this.state.animate.x&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;updatedOffsetX&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// Initialize value we'll use to update this.state.latestPosition&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;newPosition&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the variables we'll need declared, let's think about what we want to achieve with keeping the  component within it's parent. We want to prevent the component from being dragged "out of bounds". To prevent this, we need to quantify what the numeric boundaries of the slider are. &lt;/p&gt;

&lt;p&gt;For the left/minimum side of the slider, the value would simply be &lt;code&gt;0&lt;/code&gt;. If the value of &lt;code&gt;finalOffset&lt;/code&gt; is less than or equal to &lt;code&gt;0&lt;/code&gt;, we know that the user has reached the left edge of the slider. &lt;/p&gt;

&lt;p&gt;For the right/maximum side of the slider, we can use the value of &lt;code&gt;this.maxOffset&lt;/code&gt; to determine if the user has dragged out of bounds. If the value of &lt;code&gt;finalOffset&lt;/code&gt; is greater than or equal to &lt;code&gt;this.maxOffset&lt;/code&gt;, we know we'll have to forcefully end the &lt;code&gt;PanResponder&lt;/code&gt; event.&lt;/p&gt;

&lt;p&gt;Taking these "boundary" values into consideration, we know the &lt;code&gt;finalOffset&lt;/code&gt; of an "in bounds" drag would fall within the range of &lt;code&gt;0&lt;/code&gt; and &lt;code&gt;this.maxOffset&lt;/code&gt;, so a conditional would look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// If drag is "in bounds"&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;finalOffset&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;finalOffset&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;maxOffset&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Handle logic for an in bounds drag here&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Naturally, we'd expand this logic with a simple &lt;code&gt;else&lt;/code&gt; block to determine the logic we'd use for an "out of bounds" drag. We'll do that next:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// If drag is "in bounds"&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;finalOffset&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;finalOffset&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;maxOffset&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Handle logic for an in bounds drag here&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// If drag is "out of bounds"&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Handle logic here&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this logic in place we're fundamentally designating two types of drags of our component: one that is within the bounds of the slider container and one that is out of bounds. &lt;/p&gt;

&lt;p&gt;Within each of these types of drags we have three more scenarios: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The user drags and it ends up to the left of its beginning position.&lt;/li&gt;
&lt;li&gt;The user drags the component and it ends up to the right of its beginning position.&lt;/li&gt;
&lt;li&gt;The user drags it and it ends up in the exact same position. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now let's determine the logic for each of these scenarios. We'll start with the user dragging to the left. We should be able to tell if the user has moved to the left if the value of &lt;code&gt;gesture.dx&lt;/code&gt; is negative. If this is the case, we'll set &lt;code&gt;updatedOffsetX&lt;/code&gt; to the negation of &lt;code&gt;this.state.latestPosition - newPosition&lt;/code&gt;. This will give us the value of how far the user dragged to the left from the position of the component prior to it being moved.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// If drag is in bounds&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;finalOffset&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;finalOffset&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;maxOffset&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Set newPosition to that of finalOffset&lt;/span&gt;
  &lt;span class="nx"&gt;newPosition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;finalOffset&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// If moved to the left&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gesture&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dx&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Set udatedOffsetX to negation of state.latestPosition - newPosition&lt;/span&gt;
    &lt;span class="nx"&gt;updatedOffsetX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;latestPosition&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;newPosition&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, below the handler's main &lt;code&gt;if/else&lt;/code&gt; block:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pass &lt;code&gt;updatedOffsetX&lt;/code&gt; to the &lt;code&gt;x&lt;/code&gt; value in &lt;code&gt;this.state.animate.setValue()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Call &lt;code&gt;this.setState()&lt;/code&gt;, updating the value of &lt;code&gt;this.state.latestPosition&lt;/code&gt; to the the value of &lt;code&gt;newPosition&lt;/code&gt;. &lt;/li&gt;
&lt;li&gt;Move the call to &lt;code&gt;flattenOffset()&lt;/code&gt; to the bottom of the function.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your handler should now look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;panResponderReleaseHandler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gesture&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Get the final value that user has dragged to.&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;finalOffset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;gesture&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dx&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;latestPosition&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Initialize value we'll use to update this.state.animate.x&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;updatedOffsetX&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// Initialize value we'll use to update this.state.latestPosition&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;newPosition&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// If drag is in bounds&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;finalOffset&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;finalOffset&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;maxOffset&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Set newPosition to that of finalOffset&lt;/span&gt;
      &lt;span class="nx"&gt;newPosition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;finalOffset&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="c1"&gt;// If moved to the left&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gesture&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dx&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Set udatedOffsetX to negation of state.latestPosition - newPosition&lt;/span&gt;
        &lt;span class="nx"&gt;updatedOffsetX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;latestPosition&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;newPosition&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// If drag is "out of bounds"&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Handle logic here&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Update x value of this.state.animate&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;animate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;updatedOffsetX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// Update latestPosition&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;latestPosition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;newPosition&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// Merges the offset value into the base value and resets the offset to zero&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;animate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;flattenOffset&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this current form of &lt;code&gt;panResponderReleaseHandler()&lt;/code&gt;, we'll simply add more conditional statements to handle our other cases. &lt;/p&gt;

&lt;p&gt;The conditional for the component being moved to the right simply checks if &lt;code&gt;gesture.dx&lt;/code&gt; is positive; if it is we'll set &lt;code&gt;updatedOffsetX&lt;/code&gt; to the value of &lt;code&gt;newPosition - this.state.latestPosition&lt;/code&gt;. This gives us the distance that the user has moved the component to the right from the starting point of the touch event.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// If moved to the left&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gesture&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;dx&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Set udatedOffsetX to negation of state.latestPosition - newPosition&lt;/span&gt;
  &lt;span class="n"&gt;updatedOffsetX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;latestPosition&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;newPosition&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// If moved to the right&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="nf"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gesture&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;dx&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Set updatedOffsetX to newPosition - this.state.latestPosition&lt;/span&gt;
  &lt;span class="n"&gt;updatedOffsetX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;newPosition&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;latestPosition&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we need to add an &lt;code&gt;else&lt;/code&gt; block to handle the rare event that the user retuns to exactly the same spot along the slider. If that's the case we simply set &lt;code&gt;updatedOffsetX&lt;/code&gt; to &lt;code&gt;0&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// If drag is in bounds&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;finalOffset&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;finalOffset&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;maxOffset&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Set newPosition to that of finalOffset&lt;/span&gt;
  &lt;span class="nx"&gt;newPosition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;finalOffset&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// If moved to the left&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gesture&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dx&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Set udatedOffsetX to negation of state.latestPosition - newPosition&lt;/span&gt;
    &lt;span class="nx"&gt;updatedOffsetX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;latestPosition&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;newPosition&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// If moved to the right&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gesture&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dx&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Set updatedOffsetX to newPosition - this.state.latestPosition&lt;/span&gt;
    &lt;span class="nx"&gt;updatedOffsetX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;newPosition&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;latestPosition&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// If user returns to original position prior to this panResponder touch&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Set updatedOffsetX to 0&lt;/span&gt;
    &lt;span class="nx"&gt;updatedOffsetX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, test your progress. You should have everything working as long as you keep &lt;code&gt;&amp;lt;Movable /&amp;gt;&lt;/code&gt; in bounds (you'll get an error if you drag out of bounds). If things look a little wacky after a couple of touch events, make sure you removed the call to &lt;code&gt;flattenOffset()&lt;/code&gt; before the conditional logic in &lt;code&gt;panResponderReleaseHandler()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now we're at the home stretch! The following logic handles out of bounds drags. Let's take it step-by-step.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;else&lt;/code&gt; block of our function's main conditional, we'll take a similar approach to the one we did with "in bound" movements. The main difference you'll see here is that we have no &lt;code&gt;else if&lt;/code&gt; logic because we'll have the same logic for drags to the right and back to the original position. &lt;/p&gt;

&lt;p&gt;In the first conditional, we'll target drags to the right boundary by checking if the value of &lt;code&gt;gesture.dx&lt;/code&gt; is greater than &lt;code&gt;0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The logic here looks similar to how we handle drags to the right for in bound movements, but we set &lt;code&gt;newPosition&lt;/code&gt; to &lt;code&gt;this.maxOffset&lt;/code&gt; and &lt;code&gt;updatedOffsetX&lt;/code&gt; to the difference of &lt;code&gt;this.maxOffset&lt;/code&gt; and &lt;code&gt;this.state.latestPosition&lt;/code&gt; instead of  &lt;code&gt;newPosition&lt;/code&gt; and &lt;code&gt;this.state.latestPosition&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// If drag is out of bounds&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// If gesture.dx is positive&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gesture&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dx&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Set newPosition to maxOffset&lt;/span&gt;
    &lt;span class="nx"&gt;newPosition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;maxOffset&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// Set value to update offset x with to maxOffset - latestPosition&lt;/span&gt;
    &lt;span class="nx"&gt;updatedOffsetX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;maxOffset&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;latestPosition&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// If gesture.dx is the same or negative &lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we just need to handle drags to the left edge and back to the starting position of the touch event. In the &lt;code&gt;else&lt;/code&gt; block, start by setting &lt;code&gt;newPosition&lt;/code&gt; to &lt;code&gt;0&lt;/code&gt;. Then we need to check if the user was already at &lt;code&gt;0&lt;/code&gt;, if they were set the value &lt;code&gt;updatedOffsetX&lt;/code&gt; to &lt;code&gt;0&lt;/code&gt;, otherwise set it to the negation of &lt;code&gt;this.state.latestPosition&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// If gesture.dx is the same or negative &lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Set newPosition to 0&lt;/span&gt;
  &lt;span class="nx"&gt;newPosition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// If already at zero&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;latestPosition&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Set updatedOffsetX to 0&lt;/span&gt;
    &lt;span class="nx"&gt;updatedOffsetX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// Set value to update offset x with to negation of latestPosition&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;updatedOffsetX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;latestPosition&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now take a look at how everything is working. If you've followed along correctly, you shouldn't be getting any more errors when dragging &lt;code&gt;&amp;lt;Movable /&amp;gt;&lt;/code&gt; out of bounds in either direction. There should just be one issue with the slider at this point: if you return to the left edge of the slider, it should look like the component doesn't &lt;em&gt;quite&lt;/em&gt; go to the edge of the slider like it does on the right edge. This is because we need to take the radius of the component into consideration like we did when we inititialized &lt;code&gt;this.initialPosition&lt;/code&gt; in the &lt;code&gt;constructor&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fmunsch-creative%2Fimage%2Fupload%2Fv1607021459%2Fslider-no-radius-compensation_i8wxsv.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fmunsch-creative%2Fimage%2Fupload%2Fv1607021459%2Fslider-no-radius-compensation_i8wxsv.gif" alt="Slider with no component radius compensation"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can compensate for the radius by subtracting &lt;code&gt;this.componentRadius&lt;/code&gt; from the value of &lt;code&gt;updatedOffsetX&lt;/code&gt; in the &lt;code&gt;else&lt;/code&gt; statement &lt;em&gt;if the user isn't already at the left edge of the component&lt;/em&gt;. Instead of using &lt;code&gt;this.state.latestPosition&lt;/code&gt; to determine this, let's add a very explicit boolean value in local state, &lt;code&gt;atMinValue&lt;/code&gt;. Initialize it as false in the &lt;code&gt;constructor&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Initialize state&lt;/span&gt;
&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Create instance of Animated.XY, which interpolates X and Y values&lt;/span&gt;
  &lt;span class="na"&gt;animate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ValueXY&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;latestPosition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;initialPosition&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;atMinValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Back in &lt;code&gt;else&lt;/code&gt; block of the out of bounds conditional in &lt;code&gt;panResponderReleaseHandler()&lt;/code&gt;,  we want to subtract the value of &lt;code&gt;this.componentRadius&lt;/code&gt; from &lt;code&gt;updatedOffsetX&lt;/code&gt; if we're not already at the minimum value. We'll also always set &lt;code&gt;this.state.atMinValue&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt; at this point.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt; &lt;span class="c1"&gt;// Set value to update offset x with to negative value of latestPosition&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;updatedOffsetX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;latestPosition&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// If not already atMinValue&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;atMinValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Subtract component radius from updatedOffsetX&lt;/span&gt;
    &lt;span class="nx"&gt;updatedOffsetX&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;componentRadius&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;atMinValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this solution in place, you should now be having the adverse issue with &lt;code&gt;&amp;lt;Movable /&amp;gt;&lt;/code&gt; not quite looking like it's all the way at the value of &lt;code&gt;this.maxOffset&lt;/code&gt; on a drag all the way to the right. In the conditional for a positive move, we'll add the opposite logic to add the value of the component's radius to &lt;code&gt;updateOffsetX&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// If gesture.dx is positive&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gesture&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dx&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Set newPosition to maxOffset&lt;/span&gt;
  &lt;span class="nx"&gt;newPosition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;maxOffset&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// Set value to update offset x with to maxOffset - latestPosition&lt;/span&gt;
  &lt;span class="nx"&gt;updatedOffsetX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;maxOffset&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;latestPosition&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// If coming from minValue/0&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;atMinValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Add component radius to updatedOffsetX&lt;/span&gt;
    &lt;span class="nx"&gt;updatedOffsetX&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;componentRadius&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// Update state.atMinValue&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;atMinValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fmunsch-creative%2Fimage%2Fupload%2Fv1607021571%2Fslider-finished-product_xzksd9.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fmunsch-creative%2Fimage%2Fupload%2Fv1607021571%2Fslider-finished-product_xzksd9.gif" alt="Finished Slider"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With this logic in place, our slider should be finished. Of course you'll likely want to add some additional logic to "snap" to a pressed location, to set a minimum and maximum value with new props, or to tailor the &lt;code&gt;PanResponder&lt;/code&gt; handlers to your own unique needs, but this should give you a good foundation to build off of to fit your needs.&lt;/p&gt;

&lt;p&gt;Thanks for reading and for following along! :) Happy coding.&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>react</category>
      <category>animated</category>
      <category>panresponder</category>
    </item>
    <item>
      <title>Building a Movable Animated Component in React Native</title>
      <dc:creator>Ryan Munsch</dc:creator>
      <pubDate>Fri, 23 Oct 2020 21:43:36 +0000</pubDate>
      <link>https://forem.com/rmunschie92/building-a-movable-animated-component-in-react-native-4o96</link>
      <guid>https://forem.com/rmunschie92/building-a-movable-animated-component-in-react-native-4o96</guid>
      <description>&lt;p&gt;While building out the front end of a mobile application for a large client, my team and I found ourselves in need of a React Native input component similar to an HTML range-type input. The desired functionality was for a user to pick a single value from 0-10 along a range input by either “sliding” the input cursor or pressing on a section of the component. We started calling this hypothetical component a “slider” or a “slider picker”, so that’s the language I’ll be using from here on out in regards to it.&lt;/p&gt;

&lt;p&gt;We struggled to find an npm package for this functionality that got along with our existing stack and the version of Expo we were forced to use at the time, so I was tasked with building out the component. I spent a couple of days building out a rudimentary first version that was &lt;em&gt;not great&lt;/em&gt;. It didn’t really slide so much as it allowed presses within the dimensions of the component, but we needed to get the app’s MVP out the door so this was our reality for now. &lt;/p&gt;

&lt;p&gt;Eventually, there was time for me to refactor the existing component. Using the React Native &lt;a href="https://reactnative.dev/docs/animated" rel="noopener noreferrer"&gt;Animated&lt;/a&gt; and &lt;a href="https://reactnative.dev/docs/panresponder" rel="noopener noreferrer"&gt;PanResponder&lt;/a&gt; APIs, I was able to make a proper slider component that I was proud of. &lt;/p&gt;

&lt;p&gt;In this first of two articles I’ll walk you through the process of building a moveable React Native component that the user can “drag” around the screen, and in doing so we’ll develop a foundational understanding of the Animated and PanResponder React Native APIs. In a subsequent article, I'll be walking through the steps to convert a simple moveable component into an actual slider input.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A bare-bones look at what we’ll build&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fmunsch-creative%2Fimage%2Fupload%2Fv1603488044%2Fmovable-dot_pfs0vk.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fmunsch-creative%2Fimage%2Fupload%2Fv1603488044%2Fmovable-dot_pfs0vk.gif" alt="Finished product of component"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Getting started&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When I’m prototyping for React Native, I like to do it in a sample repo with as little overhead as possible; I recommend doing the same before integrating the slider into any project.&lt;/p&gt;

&lt;p&gt;The only dependency necessary for building out our slider is &lt;a href="https://github.com/graftonstudio/react-native-css-vh-vw#readme" rel="noopener noreferrer"&gt;react-native-css-vh-vw&lt;/a&gt;, a ditto of the vh and vw units in CSS for React Native. This package itself has no dependencies and at the time of writing this is under 4kb.&lt;/p&gt;

&lt;p&gt;Let’s start with installing our sole dependency. At the root of your project, run the following in your terminal:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install react-native-css-vh-vw&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now let’s go ahead and start with some boilerplate in &lt;code&gt;Movable.js&lt;/code&gt;.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Animated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;PanResponder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;StyleSheet&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-native&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;vh&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;vw&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-native-css-vh-vw&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Movable&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

   &lt;span class="c1"&gt;// Initialize state&lt;/span&gt;
   &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="c1"&gt;// Create instance of Animated.XY, which interpolates&lt;/span&gt;
     &lt;span class="c1"&gt;// X and Y values&lt;/span&gt;
     &lt;span class="na"&gt;animate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ValueXY&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// Inits both x and y to 0&lt;/span&gt;
   &lt;span class="p"&gt;};&lt;/span&gt;

   &lt;span class="c1"&gt;// Set value of x and y coordinate&lt;/span&gt;
   &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;animate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

   &lt;span class="p"&gt;[...]&lt;/span&gt; 
 &lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Here in &lt;code&gt;Movable.js&lt;/code&gt;, we’ve got our boilerplate along with the first bit of logic we need for getting going with Animated and PanResponder.&lt;/p&gt;

&lt;p&gt;While we’re at it, let’s make a component that will act as the container/screen for &lt;code&gt;Movable.js&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;StyleSheet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;View&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-native&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;vh&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;vw&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-native-css-vh-vw&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Movable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../components/Generics/Movable&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Container&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;View&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;container&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
       &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Movable&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/View&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;   &lt;span class="p"&gt;);&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;styles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;StyleSheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
 &lt;span class="na"&gt;container&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;vh&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
   &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#fff&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="na"&gt;alignItems&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;center&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="na"&gt;justifyContent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;center&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;First, we have some configuring to do with the &lt;a href="https://reactnative.dev/docs/animated" rel="noopener noreferrer"&gt;Animated API&lt;/a&gt; - in the component’s constructor we initialize &lt;code&gt;this.state.animate&lt;/code&gt;, setting it to &lt;strong&gt;new&lt;/strong&gt; &lt;code&gt;Animated.ValueXY()&lt;/code&gt; &lt;em&gt;(docs&lt;/em&gt; &lt;a href="https://reactnative.dev/docs/animatedvaluexy" rel="noopener noreferrer"&gt;&lt;em&gt;here&lt;/em&gt;&lt;/a&gt;&lt;em&gt;)&lt;/em&gt; and immediately call &lt;a href="https://reactnative.dev/docs/0.5/animatedvalue#setvalue" rel="noopener noreferrer"&gt;setValue()&lt;/a&gt; on it. When this eventually gets passed to our instance of &lt;code&gt;&amp;lt;Animated.View&amp;gt;&lt;/code&gt; it sets the x/y position of the component when it is rendered, relative to any styling you may place on it through the style prop. For example, I could execute &lt;code&gt;this.state.animate.setValue({ x: 200, y: -150 });&lt;/code&gt; and when the component first renders, it will be positioned 200 pixels to the right and 150 above the center of the screen (because the parent container is styled to position content vertically and horizontally).&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: In addition to React Native’s official docs, I also found&lt;/em&gt; &lt;a href="https://animationbook.codedaily.io/animated-value-xy" rel="noopener noreferrer"&gt;&lt;em&gt;this&lt;/em&gt;&lt;/a&gt; &lt;em&gt;page from&lt;/em&gt; &lt;a href="https://animationbook.codedaily.io/" rel="noopener noreferrer"&gt;&lt;em&gt;https://animationbook.codedaily.io/&lt;/em&gt;&lt;/a&gt; &lt;em&gt;helpful in understanding &lt;code&gt;Animated.ValueXY()&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

 &lt;span class="p"&gt;[...]&lt;/span&gt;

   &lt;span class="c1"&gt;// Initialize panResponder and configure handlers&lt;/span&gt;
   &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_panResponder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;PanResponder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
     &lt;span class="c1"&gt;//     &lt;/span&gt;
     &lt;span class="c1"&gt;// Asks to be the touch responder for a&lt;/span&gt;
     &lt;span class="c1"&gt;// press on the View&lt;/span&gt;
     &lt;span class="c1"&gt;//&lt;/span&gt;
     &lt;span class="na"&gt;onMoveShouldSetPanResponder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="c1"&gt;//&lt;/span&gt;
     &lt;span class="c1"&gt;// Actions taken when the View has begun&lt;/span&gt;
     &lt;span class="c1"&gt;// responding to touch events&lt;/span&gt;
     &lt;span class="c1"&gt;//&lt;/span&gt;
     &lt;span class="na"&gt;onPanResponderGrant&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="c1"&gt;//&lt;/span&gt;
       &lt;span class="c1"&gt;// Set offset state.animate to prevent&lt;/span&gt;
       &lt;span class="c1"&gt;// Animated.View from returning to 0      &lt;/span&gt;
       &lt;span class="c1"&gt;// coordinates when it is moved again.&lt;/span&gt;
       &lt;span class="c1"&gt;//&lt;/span&gt;
       &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;animate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setOffset&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
         &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;animate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;animate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_value&lt;/span&gt;
       &lt;span class="p"&gt;});&lt;/span&gt;
       &lt;span class="c1"&gt;//&lt;/span&gt;
       &lt;span class="c1"&gt;// Set value to 0/0 to prevent AnimatedView&lt;/span&gt;
       &lt;span class="c1"&gt;// from "jumping" on start of&lt;/span&gt;
       &lt;span class="c1"&gt;// animate. Stabilizes the component.&lt;/span&gt;
       &lt;span class="c1"&gt;//&lt;/span&gt;
       &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;animate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
     &lt;span class="p"&gt;},&lt;/span&gt;
     &lt;span class="c1"&gt;//&lt;/span&gt;
     &lt;span class="c1"&gt;// The user is moving their finger&lt;/span&gt;
     &lt;span class="c1"&gt;//&lt;/span&gt;
     &lt;span class="na"&gt;onPanResponderMove&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;gesture&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="c1"&gt;//&lt;/span&gt;
       &lt;span class="c1"&gt;// Set value of state.animate x/y to the&lt;/span&gt;
       &lt;span class="c1"&gt;// delta value of each&lt;/span&gt;
       &lt;span class="c1"&gt;//&lt;/span&gt;
       &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;animate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
         &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;gesture&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;gesture&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dy&lt;/span&gt;
       &lt;span class="p"&gt;});&lt;/span&gt;
     &lt;span class="p"&gt;},&lt;/span&gt;
     &lt;span class="c1"&gt;//&lt;/span&gt;
     &lt;span class="c1"&gt;// Fired at the end of the touch&lt;/span&gt;
     &lt;span class="c1"&gt;//&lt;/span&gt;
     &lt;span class="na"&gt;onPanResponderRelease&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="c1"&gt;//&lt;/span&gt;
       &lt;span class="c1"&gt;// Merges the offset value into the&lt;/span&gt;
       &lt;span class="c1"&gt;// base value and resets the offset&lt;/span&gt;
       &lt;span class="c1"&gt;// to zero&lt;/span&gt;
       &lt;span class="c1"&gt;//&lt;/span&gt;
       &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;animate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;flattenOffset&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
     &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// End of constructor&lt;/span&gt;

  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;View&lt;/span&gt;
       &lt;span class="c1"&gt;// Pass all panHandlers to our AnimatedView&lt;/span&gt;
       &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_panResponder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;panHandlers&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
       &lt;span class="c1"&gt;//&lt;/span&gt;
       &lt;span class="c1"&gt;// getLayout() converts {x, y} into &lt;/span&gt;
       &lt;span class="c1"&gt;// {left, top} for use in style&lt;/span&gt;
       &lt;span class="c1"&gt;//&lt;/span&gt;
       &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{[&lt;/span&gt;
         &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;animate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getLayout&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
         &lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt;
       &lt;span class="p"&gt;]}&lt;/span&gt;
     &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;   &lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Copy and paste the contents of the above code block into &lt;code&gt;Movable.js&lt;/code&gt;and open up the iOS simulator on your machine (for now let’s ignore the actual contents of the code and make sure it’s working as expected). Your output should look very close to the gif above and have the same functionality.&lt;/p&gt;

&lt;p&gt;With the simple movable component working, let’s take a further look into the code that provides us with the desired functionality.&lt;/p&gt;

&lt;p&gt;For now, disregard any of the code that is within the &lt;code&gt;render()&lt;/code&gt; function; we’ll get to that in a bit.&lt;/p&gt;

&lt;p&gt;Divert your attention to the code we’ve added to the component’s &lt;code&gt;constructor()&lt;/code&gt;. We’ve created an instance of PanResponder and configured its handlers. The &lt;a href="https://reactnative.dev/docs/panresponder" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; for the API is a bit confusing in my opinion &lt;em&gt;(the&lt;/em&gt; &lt;a href="https://reactnative.dev/docs/panresponder#usage-pattern" rel="noopener noreferrer"&gt;&lt;em&gt;Usage Pattern&lt;/em&gt;&lt;/a&gt; &lt;em&gt;section is helpful)&lt;/em&gt;, but the main takeaway is that it converts a series of touches into a single gesture, so that “drag” of a finger is really a series of several touch events that are consolidated into one. To achieve this functionality, the API uses a tweaked version of the &lt;a href="https://reactnative.dev/docs/gesture-responder-system" rel="noopener noreferrer"&gt;Gesture Responder System&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;To use PanResponder, you’ll need to &lt;a href="https://reactnative.dev/docs/panresponder#create" rel="noopener noreferrer"&gt;create&lt;/a&gt; an instance and pass an object of key/value pair handlers. Reference the code block above to see the behavior and usage of each handler needed for a simple draggable component. We’ll be passing an arrow function to each handler to set the desired behavior. Let’s walk through that configuration object, one handler at a time.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: We won’t be using every PanResponder handler available.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The first key we’ll pass to &lt;code&gt;PanResponder.create()&lt;/code&gt; is &lt;code&gt;onMoveShouldSetPanResponder&lt;/code&gt;, which simply returns &lt;code&gt;true&lt;/code&gt;. You can think of this as telling the View with the handler that it can “claim” the touch event taking place.&lt;/p&gt;

&lt;p&gt;Second is &lt;code&gt;onPanResponderGrant&lt;/code&gt;: this is where any logic will take place that we want executed when the &lt;code&gt;View&lt;/code&gt; has started responding to touch events. Here, we need to call two functions for our instance of &lt;code&gt;AnimatedValue&lt;/code&gt; stored in &lt;code&gt;this.state.animate - setOffset()&lt;/code&gt; and &lt;code&gt;setValue()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;According to the React Native docs, &lt;code&gt;setOffset()&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;“Sets an offset that is applied on top of whatever value is set, whether via &lt;code&gt;setValue&lt;/code&gt;, an animation, or &lt;code&gt;Animated.event&lt;/code&gt;. Useful for compensating things like the start of a pan gesture.” In the context of our example, we pass an object with a key/value pair for both x and y to &lt;code&gt;setOffset()&lt;/code&gt;, each value the respective one of &lt;code&gt;this.state.animate&lt;/code&gt; at the time when the touch event has begun.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;animate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setOffset&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;animate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;animate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_value&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now when the touch event begins, an update to the value of &lt;code&gt;this.state.animate&lt;/code&gt; accounts for the value of its most recent &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; offsets; without this the values would update in relation to the values for &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; that you set when you first called &lt;code&gt;this.state.animate.setValue()&lt;/code&gt; in the constructor (in our case &lt;code&gt;x: 0&lt;/code&gt;,&lt;code&gt;y: 0&lt;/code&gt;). To see what this logic really offers our little app, let’s remove it. Comment out this line of code, refresh your Simulator, and try moving around the component again and see how behavior changes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fmunsch-creative%2Fimage%2Fupload%2Fv1603488624%2FsetOffset-tinkering_xhpp81.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fmunsch-creative%2Fimage%2Fupload%2Fv1603488624%2FsetOffset-tinkering_xhpp81.gif" alt="Component with incorrect setOffset() logic"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Still within &lt;code&gt;onPanResponderGrant&lt;/code&gt;, we execute &lt;code&gt;this.state.animate.setValue()&lt;/code&gt; once again passing an object with a key/value pair for both &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt;, this time with them both set to zero. Let’s take a quick look at what the React Native docs have to say about this method: “Directly set the value. This will stop any animations running on the value and update all the bound properties.” To use layman’s terms, this prevents the possibility of our animated component from “jumping” around the container at the beginning of a touch event. At this point, calling &lt;code&gt;setValue()&lt;/code&gt; here is more of a precautionary measure, but it will have clearer implications when we start converting this component into an actual Slider. Like with &lt;code&gt;setOffset()&lt;/code&gt;, let’s tweak this line of code to get a better sense of what it does: change the &lt;code&gt;x&lt;/code&gt; value to &lt;code&gt;1000&lt;/code&gt; and the &lt;code&gt;y&lt;/code&gt; value to &lt;code&gt;50&lt;/code&gt;, refresh your Simulator, and try moving the component around again.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fmunsch-creative%2Fimage%2Fupload%2Fv1603488904%2FsetValue-tinkering_a7bvbj.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fmunsch-creative%2Fimage%2Fupload%2Fv1603488904%2FsetValue-tinkering_a7bvbj.gif" alt="Component with incorrect setOffset() logic"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The next PanResponder handler is &lt;code&gt;onPanResponderMove&lt;/code&gt;, the handler for when the user moves their finger during the touch event. For this handler, we’ll be using one of the two parameters that can be passed to each PanResponder handler, &lt;code&gt;gestureState&lt;/code&gt;. The other parameter is &lt;code&gt;nativeEvent&lt;/code&gt;, which we must still pass even though we won’t be using it (see the PanResponder docs for a detailed look at each parameter). We’re going to take two values within &lt;code&gt;gestureState&lt;/code&gt; and pass them to &lt;code&gt;this.state.animate.setValue()&lt;/code&gt;, &lt;code&gt;gestureState.dx&lt;/code&gt; and &lt;code&gt;gestureState.dy&lt;/code&gt;. &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// The user is moving their finger&lt;/span&gt;
&lt;span class="nx"&gt;onPanResponderMove&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;gesture&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Set value of state.animate x/y to the delta value of each&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;animate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;gesture&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;gesture&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dy&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;These two values are relatively straightforward; according to the &lt;a href="https://reactnative.dev/docs/panresponder" rel="noopener noreferrer"&gt;docs&lt;/a&gt;, they represent “accumulated distance of the gesture since the touch started” for each respective axis. Let’s say you move the component 50 pixels to the left, &lt;code&gt;gesture.dx&lt;/code&gt; will have a value of &lt;code&gt;-50&lt;/code&gt;. If you move the component 125 pixels towards the bottom of the device’s screen, &lt;code&gt;gesture.dy&lt;/code&gt; will have a value of &lt;code&gt;125&lt;/code&gt;. Gestures of the same distance in the opposite direction would be &lt;code&gt;50&lt;/code&gt; and &lt;code&gt;125&lt;/code&gt; respectively.&lt;/p&gt;

&lt;p&gt;The final PanResponder handler used is &lt;code&gt;onPanResponderRelease&lt;/code&gt;, which is fired at the end of the touch when the user lifts their finger. In cases where you’d like to set a local state value or execute a callback to hoist state to a parent container, this is likely the best handler to do it in. For now, we simply call &lt;code&gt;flattenOffset()&lt;/code&gt; on &lt;code&gt;this.state.animate&lt;/code&gt; - according to the &lt;a href="https://reactnative.dev/docs/animatedvaluexy#flattenoffset" rel="noopener noreferrer"&gt;docs&lt;/a&gt;, this “merges the offset value into the base value and resets the offset to zero.”[1] This merge happens without changing the output value of the animation event. If we remove &lt;code&gt;flattenOffset()&lt;/code&gt; the first one or two drags of our component look ok, but continued drags will show the problem with not resetting the offset value.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fmunsch-creative%2Fimage%2Fupload%2Fv1603489069%2FflattenOffset_-tinkering_enu5yl.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fmunsch-creative%2Fimage%2Fupload%2Fv1603489069%2FflattenOffset_-tinkering_enu5yl.gif" alt="No flattenOffset() example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With our PanResponder handlers configured, let’s turn our attention to what’s going on inside of our &lt;code&gt;render()&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;Instead of using a normal &lt;code&gt;View&lt;/code&gt; component, we use the &lt;code&gt;Animated.View&lt;/code&gt; component and pass all the PanResponder handlers as props using an object with the JavaScript spread operator. Finally, we pass an array to the component’s style prop with whatever styles you’d like to apply to your component (I’ve included mine below), along with a call to &lt;code&gt;this.state.animate.getLayout()&lt;/code&gt; - which converts the &lt;code&gt;Animated&lt;/code&gt; instance’s &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; values to left and top style values respectively.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;styles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;StyleSheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;button&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;vw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;vw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;borderRadius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;vw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;borderWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now we have a fully moveable React Native component! It’s not much at this point, but feel free to continue along in the following article to finish building out our Slider component.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Thanks for reading! The second article is coming very soon!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>react</category>
      <category>animated</category>
      <category>panresponder</category>
    </item>
  </channel>
</rss>
