<?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>DEV Community: Sebastijan Dumancic</title>
    <description>The latest articles on DEV Community by Sebastijan Dumancic (@sebastijandumancic).</description>
    <link>https://dev.to/sebastijandumancic</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%2F214618%2F1086b775-f490-4dae-bacb-80933fdcd057.jpeg</url>
      <title>DEV Community: Sebastijan Dumancic</title>
      <link>https://dev.to/sebastijandumancic</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sebastijandumancic"/>
    <language>en</language>
    <item>
      <title>The thing about service workers...</title>
      <dc:creator>Sebastijan Dumancic</dc:creator>
      <pubDate>Fri, 25 Sep 2020 08:10:43 +0000</pubDate>
      <link>https://dev.to/prototyp/the-thing-about-service-workers-2k97</link>
      <guid>https://dev.to/prototyp/the-thing-about-service-workers-2k97</guid>
      <description>&lt;p&gt;For years, service workers have promised us a feeling of a native app straight in the browser. While specific parts of it are true, such as access to device hardware (gyroscope, orientation sensor, etc.) or background sync, we're still far cry from the native feel in areas such as push notifications, which don't work at all in iOS, and especially offline support. While it's fun to have options and experiment on private, small projects, we can't really consider technologies to be production-ready when they don't support half the devices out there.&lt;/p&gt;

&lt;p&gt;With that in mind, service workers also come with a lot of baggage. &lt;em&gt;And we've found that out in a hard way.&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Problem with service workers
&lt;/h1&gt;

&lt;p&gt;First, you start developing your app, include service worker because it's a cool new thing to do, you want offline support or definitely want to have all the stuff they bring as an option to use. Months go by, you release v1 of the app and users start rolling in. As it's the first version, things are bound to change, so you implement the first couple of changes. You maybe change some copy around, some links, but soon you get a report that you have a huge bug discovered by one of your users. Maybe something potentially catastrophic for your database, it happens. &lt;/p&gt;

&lt;p&gt;Fear not, you patch it up and go about your day. Months go by, and you release v2 of the app, market it like crazy and it reaches some top lists of this and that, and same users that entered your app a couple of months ago, and never again, land on your page and load a completely cached version from the last time they visited, together with any hardcoded values, bugs, funnel changes... essentially a snapshot from the past.&lt;/p&gt;

&lt;p&gt;By the time you realize what you have done, you've already saved a snapshot of the app in the arbitrary time to thousands of devices, unable to wipe the cache on their devices, and just sit and wait for them to potentially open your older, less secure version of the app from months ago. &lt;/p&gt;

&lt;h1&gt;
  
  
  Potential solutions
&lt;/h1&gt;

&lt;p&gt;The way service worker works is when users land on your website for the 2nd time, it loads all assets and files from SW and THEN checks if you have pushed a new SW update in the meantime. If it finds one, it schedules it to be loaded next time you open the website. To make matters worse, normal refresh won't load the new SW content, but you have to close the session (i.e. close all website tabs currently open, or whole browser) and reopen the website to load the new version. &lt;/p&gt;

&lt;p&gt;By following this article: &lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag__link"&gt;
  &lt;a href="/glukmann" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F288075%2Fd8e2dcd6-c87f-428e-aa4b-330fc8d88f61.jpg" alt="glukmann"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/glukmann/let-users-know-when-you-have-updated-your-service-worker-in-create-react-app-3il9" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Let Users Know When You Have Updated Your Service Workers in Create React App&lt;/h2&gt;
      &lt;h3&gt;Gert Glükmann ・ Jan 4 '20&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#react&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#serviceworkers&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#pwa&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;I found out that you can insert an action into this process of discovering the new version of SW. The problem is that you can either notify users that a new version is available and leave it up to them to click &lt;strong&gt;Load new version&lt;/strong&gt; which will reload the website properly, or you can force a refresh when the browser figures out that a new SW version is available and installed, which can be after a couple of seconds and well into the time when the app was already interactive, meaning that user started to do something. &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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1d8p5yhkyec2xahxcppa.png" 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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1d8p5yhkyec2xahxcppa.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Usually, early in the live of an app, updates could be released several times a day, which means users could get a prompt or hard refresh multiple times a day when they land on a website, which is also not a good option.&lt;/p&gt;

&lt;p&gt;Other way around, we leave ourselves open to the ghosts of the past by giving users the option to load a new version of the site or not. This way malicious users could take advantage of the app in its pre-patched state.&lt;/p&gt;

&lt;p&gt;The worst thing is, when you decide to change your approach, you still have all the old users cached on your previous decision and they don't get the memo that they should reload as soon as they open the site. &lt;/p&gt;

&lt;p&gt;Now, when you think about it, it becomes obvious that this is how native apps work from the start. You have a version that is the latest and a lot of previous versions that people have installed, and are still using. &lt;em&gt;But the web isn't native&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;Addon: &lt;br&gt;
As &lt;strong&gt;leob&lt;/strong&gt; mentioned in the comments (thanks!) some apps force users to update to new versions even in the native environment. Banking apps first come to mind, which just confirms that the issue exists and if security is an important priority for us, that we have to address it in a creative way.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Many years ago, Web solved the issue where users had to install a new version of software on their devices, where we had to incentivize them to update or upgrade, and support legacy versions with both features and bugfixes. We approach web development with a different mindset than native development. We KNOW we can push updates very quickly to 100% percent of our users, and we are used to pushing experimental features, knowing very well that we can patch them up as we go or remove them fairly quickly if they turn out to be bad ideas. Including service workers turn the tables around once again, by introducing fragmentation, legacy support, and fear of the unknown on the internet, which is something that should be avoided at all costs. &lt;/p&gt;

&lt;p&gt;Sure, if we create just a couple of versions all of which are perfect, this is a non-issue, but let's be real, those apps don't exist. So how do you deal with these issues if you still want to keep offline support? Do you use service workers at all? Let me know! &lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Draggable chat-heads in React Native</title>
      <dc:creator>Sebastijan Dumancic</dc:creator>
      <pubDate>Tue, 24 Sep 2019 08:20:39 +0000</pubDate>
      <link>https://dev.to/prototyp/draggable-chat-heads-in-react-native-4f1g</link>
      <guid>https://dev.to/prototyp/draggable-chat-heads-in-react-native-4f1g</guid>
      <description>&lt;p&gt;Most of us are familiar with Facebook’s floating heads that are screaming for your attention on top of all other apps. At the time, it was a novel concept, somewhat annoying, but still, something new.&lt;/p&gt;

&lt;p&gt;Recently, we’ve had a client that requested similar behavior, just in-app, which would show draggable profile photos which could be paired by overlapping one over another.&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F7zfkuqgp507z0gfy6pau.png" 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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F7zfkuqgp507z0gfy6pau.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since you’re probably skimming this part to see if a solution you’re looking forward is here, let get straight to the point.&lt;/p&gt;

&lt;p&gt;We’ve used &lt;strong&gt;panResponder&lt;/strong&gt; and wrapped each person in one.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&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="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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addListener&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="o"&gt;=&amp;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;position&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value&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="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="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="nx"&gt;evt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;gestureState&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="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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pan&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;position&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="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;position&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pan&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;// Move object while onPress is active. Snapping is handled later.&lt;/span&gt;
            &lt;span class="na"&gt;onPanResponderMove&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="nf"&gt;event&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
                &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;dx&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;pan&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="na"&gt;dy&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;pan&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="p"&gt;]),&lt;/span&gt;

            &lt;span class="c1"&gt;// Handle swiper behaviour after object is released.&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="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&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="nx"&gt;dy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;vx&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;// Fix jumping when moving the object second time.&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;pan&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="c1"&gt;// Send ending position to parent component.&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="nf"&gt;calculateOverlapping&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="nx"&gt;dy&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;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

                &lt;span class="c1"&gt;// Animate springy tuff.&lt;/span&gt;
                &lt;span class="nx"&gt;Animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;spring&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;pan&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;toValue&lt;/span&gt;&lt;span class="p"&gt;:&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="nf"&gt;start&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  &lt;strong&gt;Register initial people position&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Each person is wrapped in an Animated.View component which means it’s draggable. Animated.View, just as normal View, has an onLayout event which is invoked on mount and layout changes.&lt;/p&gt;

&lt;p&gt;Once that event is triggered, we can register this person initial position. They are positioned absolutely, but when reporting position it will use XY coordinates based on the parent they are on (0,0 will be top left corner of the parent element).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newPersonPosition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PersonPosition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nativeEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; 
&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nativeEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The position is truncated since we don’t need extreme precision that horizontal and vertical displacements report (&lt;strong&gt;dx&lt;/strong&gt; and &lt;strong&gt;dy&lt;/strong&gt; in &lt;strong&gt;onPanResponderRelease&lt;/strong&gt;).&lt;/p&gt;

&lt;p&gt;PersonPosition here is just a constructor that creates an object with its horizontal and vertical position, together with userId which we can use later on to trigger events on that specific user.&lt;/p&gt;

&lt;p&gt;Also, I’ve added 30, a magic number, which is half of the width and height of a component. Reported location (&lt;strong&gt;event.nativeEvent.layout.x&lt;/strong&gt;) is a position in the top left corner of the component. If you want to be scientific about this, the proper way would be to check for a component's width and height and add half of it, but I know mine is 60, so I just added half manually. Now we save this since it’s a center of a component, and we need that for overlap calculation.&lt;/p&gt;

&lt;p&gt;Position for each person is then pushed into an array which is saved to state:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;peoplePosition&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newPersonPosition&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="nx"&gt;peoplePosition&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is to have an easier way of comparing future dropped components to all of the others (using array’s find method).&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Checking for overlapping&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Main part is to check for overlapping after the user releases the person. We can get the drop coordinates like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;droppedX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;draggedPerson&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;startingPointX&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;dx&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;droppedY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;draggedPerson&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;startingPointY&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;dy&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Where we take dragged person’s horizontal starting point and add the horizontal displacement and repeat for the vertical axis. The result is once again truncated to remove unneeded decimals.&lt;/p&gt;

&lt;p&gt;Then, that &lt;strong&gt;ending&lt;/strong&gt; position of the person is checked against the positions of all people that were not dragged:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;matchedPerson&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;notDraggedPeople&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;personPosition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PersonPosition&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 
&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;personPosition&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;startingPointX&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;droppedX&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;personPosition&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;startingPointY&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;droppedY&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the dropped person is anywhere inside a set distance from any of the people, we have a match! Here the radius is hardcoded to 30px, but you can set it to whatever you want.&lt;/p&gt;

&lt;p&gt;Maybe the best is half the width of an element + some buffer to make it easier to overlap successfully. You definitely want to avoid making it larger than the total width of the elements you’re overlapping to avoid false positives.&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F9tosuj4x8j5kl9bzmjki.png" 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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F9tosuj4x8j5kl9bzmjki.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The distance of 0 means that the two components are perfectly overlapped (their centers match). Distance of 30 (in our case) means that they are touched by the edges. Tweak this number to determine how precise you have to be in order to get a sucesfull match.&lt;/p&gt;

&lt;p&gt;If a match is successful, just push the person to the &lt;strong&gt;matchedPeople&lt;/strong&gt; array and save it to the state:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;matchedPeople&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&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;matchedPerson&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;matchedPeople&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;matchedPerson&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="nx"&gt;matchedPeople&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;h1&gt;
  
  
  &lt;strong&gt;Trigger action after ovelapping&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Finally, you probably want to do something after the user overlaps two heads successfully.&lt;/p&gt;

&lt;p&gt;In our case, we just listened to state change for matchedPeople in ComponentWillUpdate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;componentWillUpdate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nextProps&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;nextState&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="p"&gt;{&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;nextState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;matchedPeople&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="c1"&gt;// Navigate away from the screen&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;You should check for changes here to avoid excessive triggering for each component updates, but since we navigated away from this screen once a successful overlaps occur (matchedPeople array is populated), it’s a simple logic to check for.&lt;/p&gt;

&lt;p&gt;Provided you’re experienced with panResponder, this code should be easy to replicate. In case you need a refresher on panResponder, I’ve written another article which tackles rotateable circle to select items here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://medium.com/prototyped/circular-swiper-using-pan-responder-and-animated-library-b78eee9784a4" rel="noopener noreferrer"&gt;https://medium.com/prototyped/circular-swiper-using-pan-responder-and-animated-library-b78eee9784a4&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Did I mess up somewhere? Have better ideas? Drop us an email at &lt;a href="mailto:hello@prototyp.digital"&gt;hello@prototyp.digital&lt;/a&gt; or visit us at &lt;a href="https://prototyp.digital" rel="noopener noreferrer"&gt;https://prototyp.digital&lt;/a&gt;. Cheers!&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>tutorial</category>
      <category>javascript</category>
      <category>react</category>
    </item>
  </channel>
</rss>
