<?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: GlyphCat</title>
    <description>The latest articles on DEV Community by GlyphCat (@glyphcat).</description>
    <link>https://dev.to/glyphcat</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%2F39412%2F598bb198-2dc0-4576-9b21-44d600fef3ef.png</url>
      <title>DEV Community: GlyphCat</title>
      <link>https://dev.to/glyphcat</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/glyphcat"/>
    <language>en</language>
    <item>
      <title>State Management with React Relink</title>
      <dc:creator>GlyphCat</dc:creator>
      <pubDate>Fri, 27 Nov 2020 13:00:35 +0000</pubDate>
      <link>https://dev.to/glyphcat/state-management-with-react-relink-3g9</link>
      <guid>https://dev.to/glyphcat/state-management-with-react-relink-3g9</guid>
      <description>&lt;p&gt;Relink is a React state management library inspired by Recoil.&lt;/p&gt;

&lt;p&gt;Recoil is Facebook's &lt;a href="https://recoiljs.org"&gt;experimental state management library&lt;/a&gt;. Shifting from Redux, I have been using Recoil for more than half a year and so far it worked well me. But the downside is that the documentations are not very complete and it comes with features that I find myself never using. For things that I &lt;em&gt;do&lt;/em&gt; need, I find myself resorting to rather awkward workarounds.&lt;/p&gt;

&lt;p&gt;One thing that I have yet to find a workaround is to get it to work with React Native Navigation. In RNN, each screen has a separate React component tree. State updates do not occur across screens since every screen is wrapped in their own .&lt;/p&gt;

&lt;p&gt;Sure, there are other tools out there that can help with state management, but since it can also be an interesting learning experience for me, I've decided to create my own state management solution.&lt;/p&gt;

&lt;h1&gt;
  
  
  Relink
&lt;/h1&gt;

&lt;p&gt;I call it Relink (or React Relink, since the name &lt;code&gt;relink&lt;/code&gt; &lt;a href="https://www.npmjs.com/package/relink"&gt;has been taken on NPM&lt;/a&gt;). Part of how Relink works is similar to Recoil. I've made it that way because I find Recoil's convention rather easy to understand.&lt;/p&gt;

&lt;p&gt;The source code is currently available on &lt;a href="https://github.com/chin98edwin/react-relink"&gt;GitHub&lt;/a&gt; and the package on &lt;a href="https://www.npmjs.com/package/react-relink"&gt;NPM&lt;/a&gt;. If you find it helpful or simply intriguing, do consider giving it a star on GitHub 😉.&lt;/p&gt;

&lt;p&gt;Below are just some basics, detailed documentations are available in the &lt;a href="https://github.com/chin98edwin/react-relink/blob/main/README.md"&gt;readme&lt;/a&gt; file.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. No provider components required 🤯
&lt;/h2&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createSource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useRelinkState&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-relink&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ScoreSource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createSource&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="c1"&gt;// key must be unique&lt;/span&gt;
  &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;score&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="c1"&gt;// This is the default state&lt;/span&gt;
  &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;red&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;blue&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;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;App&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;score&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setScore&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useRelinkState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ScoreSource&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a source then use it with a Relink hook and that's it.&lt;/p&gt;

&lt;p&gt;Under the hood, Relink hooks use listeners to trigger component updates. The states become accessible (or &lt;em&gt;linked&lt;/em&gt;) across different React component trees since there are no providers. This is also the main reason it's called "Relink". &lt;/p&gt;

&lt;p&gt;Of course, I can't say for sure if providers are necessary and whether eliminating the need for providers will cause problems, but that shouldn't be a big concern as long as the keys are unique. &lt;/p&gt;

&lt;h2&gt;
  
  
  2. Hydration &amp;amp; Persistence 🌱
&lt;/h2&gt;

&lt;p&gt;The code for managing data hydration and persistence are kept close to the source creation. You don't only have a single source of truth, but a single place to keep your hydration/persistence logic.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;counterKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;counter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;counterDefaultState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

&lt;span class="nx"&gt;createSource&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;counterKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;counterDefaultState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;lifecycle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Hydration&lt;/span&gt;
    &lt;span class="na"&gt;init&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;commit&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;counterKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nx"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;counterDefaultState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="c1"&gt;// Persistence&lt;/span&gt;
    &lt;span class="na"&gt;didSet&lt;/span&gt;&lt;span class="p"&gt;:&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;counterKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&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="c1"&gt;// Persistence by cleaning up&lt;/span&gt;
    &lt;span class="na"&gt;didReset&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="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;removeItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;counterKey&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;h2&gt;
  
  
  3. Extra Options ⚙️
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;• Suspense components during hydration&lt;/strong&gt;&lt;br&gt;
By default, hydration happens synchronously. If you're fetching data from the server, then you'll either need to turn this on or conditionally render a loading UI while hydration is in progress. This is disabled by default because it relies on an experimental React feature.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;• Enable mutability&lt;/strong&gt;&lt;br&gt;
In case you desperately need some performance improvement, you can enable mutability. This is disabled by default because it might lead to unwanted side effects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;• Virtual batching&lt;/strong&gt;&lt;br&gt;
Meant to improve performance by batching Relink's listener updates before triggering component updates on top of React's &lt;code&gt;unstable_batchedUpdates&lt;/code&gt;. This is disabled by default because it used to result in faulty component updates in the early stages and the improvements are not obvious.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;createSource&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;suspense&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;mutable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;virtualBatch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&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;em&gt;(extras)&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  A Funny Observation
&lt;/h1&gt;

&lt;p&gt;There's a funny thing that I learned along the way. At first I wanted to make it usable in React &amp;amp; React Native using the same bundled code but apparently it lead to bugs 🐛. In the end, I had to create different bundles for React DOM and React Native.&lt;/p&gt;

&lt;p&gt;As mentioned previously, Relink uses listeners. At first, I relied on &lt;code&gt;useEffect&lt;/code&gt; to add/cleanup the listeners and it created a rather confusing error. Imagine 3 components subscribing to a listener. The listener callbacks are called from components A to C in a for-loop.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┳━━━ &amp;lt;ComponentA /&amp;gt;
┗━┳━ &amp;lt;ComponentB /&amp;gt;
  ┗━━━ &amp;lt;ComponentC /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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;keyStack&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;listeners&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;for&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;key&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;keyStack&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;listeners&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&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;The callback for Component B is called and there's a chance it can cause Component C to unmount. Then when calling the callback for Component C, the callback becomes undefined since it has been removed in the cleanup function.&lt;/p&gt;

&lt;p&gt;Using &lt;code&gt;for (... i &amp;lt; listeners.length ... )&lt;/code&gt; or &lt;code&gt;for (... i &amp;lt; Object.keys(listeners).length ... )&lt;/code&gt; seemed to help a little, but it is still possible for the array of callbacks to change before a loop can complete. &lt;/p&gt;

&lt;p&gt;In the end, I resorted to &lt;code&gt;useLayoutEffect&lt;/code&gt; and React's &lt;code&gt;unstable_batchedUpdates&lt;/code&gt;. This helped to batch the renders together and solved the problem. However, the logic for batching component updates for browsers and mobile platforms are different so they need to be imported from either 'react-dom' or 'react-native' depending on the environment. Hence, different code bundles need to be generated.&lt;/p&gt;

&lt;p&gt;I have also considered using linked lists but yet to test it out. Since it's already working, I'm leaving the code as it is for now. &lt;code&gt;:3&lt;/code&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  The Bottom Line
&lt;/h1&gt;

&lt;p&gt;Don't reinvent the wheel, use what's already made by others — this is usually true. But when they start to function awkwardly, you might wanna consider manufacturing your own wheels.&lt;/p&gt;

&lt;p&gt;Facebook created Recoil to tailor to their needs despite already having several state managing solutions out there. The same can be said about Relink. &lt;/p&gt;

&lt;p&gt;Of course, nothing is perfect. If state management is important to you but nothing's working quite right and you have the capacity, may be you should try creating a solution that fits you too. 🍻&lt;/p&gt;

</description>
      <category>react</category>
      <category>statemanagement</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Enabling Exclusive Content with Web Monetization: The Right Way</title>
      <dc:creator>GlyphCat</dc:creator>
      <pubDate>Fri, 26 Jun 2020 09:26:34 +0000</pubDate>
      <link>https://dev.to/glyphcat/enabling-exclusive-content-with-web-monetization-the-right-way-3j4g</link>
      <guid>https://dev.to/glyphcat/enabling-exclusive-content-with-web-monetization-the-right-way-3j4g</guid>
      <description>&lt;p&gt;In a &lt;a href="https://dev.to/chin98edwin/making-your-payment-pointer-read-only-1d75"&gt;previous post&lt;/a&gt;, I talked about how payment pointers can be modified just like any other HTML element in the DOM tree.&lt;/p&gt;

&lt;p&gt;I came up with a solution to deal with it, if not, at least make it harder for the payment pointer to be tampered with. But as I kept on researching, I found yet another way from technical specifications in the WM (Web Monetization) official site. It's not necessarily &lt;em&gt;"the only right way"&lt;/em&gt;, but it is a rather practical way.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Missing Part
&lt;/h1&gt;

&lt;p&gt;The thing is, not even the &lt;a href="https://webmonetization.org/docs/exclusive-content#code-1"&gt;complete example&lt;/a&gt; given by WM mentions about it. &lt;/p&gt;

&lt;p&gt;When a transaction occurs and a monetization event is emitted, you can (and should) check its payment pointer via &lt;code&gt;event.detail.paymentPointer&lt;/code&gt;, if the payment pointer is different, stop showing exclusive content immediately.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;  if (document.monetization) {
&lt;span class="gd"&gt;-   document.monetization.addEventListener('monetizationstart', () =&amp;gt; {
&lt;/span&gt;&lt;span class="gi"&gt;+   document.monetization.addEventListener('monetizationstart', (event) =&amp;gt; {
+     if (event.detail.paymentPointer === MY_PAYMENT_POINTER) {
&lt;/span&gt;        showExclusiveContent()
&lt;span class="gi"&gt;+     } else {
+       hideExclusiveContent()
+     }
&lt;/span&gt;    })
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;br&gt;&lt;br&gt;
Note:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This code is based on a small portion from the example by WM&lt;/li&gt;
&lt;li&gt;I would suggest adding a listener for &lt;code&gt;'monetizationprogress'&lt;/code&gt; and check the payment pointer too just in case.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
For reference purposes, below is a screenshot showing the details from an emitted monetization event:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FI8RFuuc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/m1edrg174hnv7skvhelw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FI8RFuuc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/m1edrg174hnv7skvhelw.png" alt="Monetization Stop Event Details" width="690" height="449"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;h1&gt;
  
  
  So now,
&lt;/h1&gt;

&lt;p&gt;You know the concept of enabling exclusive content by making sure you get paid for it... with a client-side approach at least. (￣▽￣) And I'd say the Payment Pointer Protection approach is still relevant as it acts as an additional layer of safeguard. After all, it's a thing that takes place in the browser. We don't have as much control over the things that happen as we do in the backend.&lt;/p&gt;

&lt;p&gt;With that said, I shall post more updates on this topic should I find something interesting. Until then, peace. ✌️&lt;/p&gt;

</description>
      <category>html</category>
      <category>webmonetization</category>
      <category>javascript</category>
      <category>paymentpointer</category>
    </item>
    <item>
      <title>Making Your Payment Pointer "Read-only"</title>
      <dc:creator>GlyphCat</dc:creator>
      <pubDate>Fri, 26 Jun 2020 02:17:36 +0000</pubDate>
      <link>https://dev.to/glyphcat/making-your-payment-pointer-read-only-1d75</link>
      <guid>https://dev.to/glyphcat/making-your-payment-pointer-read-only-1d75</guid>
      <description>&lt;p&gt;&lt;a href="https://dev.to/devteam/dev-is-now-web-monetized-21db"&gt;DEV is now Web Monetized&lt;/a&gt; and Web Monetization itself seems to be gaining more attention lately. I started playing around with it out of curiousity. It was when I noticed a problem but not sure how great the impact would be.&lt;/p&gt;

&lt;p&gt;So I'm taking this opportunity to share a solution that I came up with, and I'd like to know your thoughts on the problem itself. &lt;/p&gt;

&lt;h1&gt;
  
  
  The Problem
&lt;/h1&gt;

&lt;p&gt;The payment pointer is just a &lt;code&gt;&amp;lt;meta&amp;gt;&lt;/code&gt; tag. Its value can be changed from a browser's element inspector and possibly through script injection.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://webmonetization.org/specification.html"&gt;specification&lt;/a&gt; states that:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The user agent generates a fresh random UUID (version 4) and uses this as a Monetization ID. This MUST be regenerated upon dynamic changes to the meta tags and MUST be unique per page load in order to avoid user tracking.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This means they are allowing the payment pointer's value to be set dynamically, right? But what if people somehow modified our payment pointer and set it to theirs while consuming our content? Yikes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QI6IbqFi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/mglwe40067telye7x7z9.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QI6IbqFi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/mglwe40067telye7x7z9.jpg" alt="Surprised Pikachu Meme" width="300" height="174"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
&lt;em&gt;Edit: So I was still doing research after finish writing this article and found something else helpful. It's a more practical way to protect your web monetized content. I've written &lt;a href="https://dev.to/chin98edwin/enabling-exclusive-content-with-web-monetization-the-right-way-3j4g"&gt;a separate article&lt;/a&gt; to explain how that method works. Nonetheless, this article will still remain relevant so please keep on reading.&lt;/em&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  A Solution
&lt;/h1&gt;

&lt;p&gt;So I started to think about ways that can protect the payment pointer, or at least, make it harder for people to tamper with and finally came up with a solution in written in JavaScript.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;p&gt;It's designed (but not guaranteed) to prevent people from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Removing your payment pointer&lt;/li&gt;
&lt;li&gt;Modifying your payment pointer&lt;/li&gt;
&lt;li&gt;Inserting their own payment pointer

&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Only time can tell if it's reliable. &lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;p&gt;The way it works is pretty simple:&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;import&lt;/span&gt; &lt;span class="nx"&gt;PaymentPointerProtector&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;./payment-pointer-protector&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;paymentPointer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$example.payment.pointer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;PaymentPointerProtector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;paymentPointer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// Start watching&lt;/span&gt;
&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;guard&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;// Stop watching&lt;/span&gt;
&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;release&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's also a wrapper that you can use in React.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;PaymentPointerProtector&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;./payment-pointer-protector/react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;paymentPointer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$example.payment.pointer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;App&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;PaymentPointerProtector&lt;/span&gt; &lt;span class="na"&gt;paymentPointer&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;paymentPointer&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&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;If you already have a payment pointer in the &lt;code&gt;head&lt;/code&gt; your HTML, it will look for the tag and guard it. Otherwise, it will add one for you then guard it.&lt;/p&gt;

&lt;p&gt;The payment pointer literally becomes read-only.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6BRnRBsI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/5fdp7bu5yur60fp72tb6.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6BRnRBsI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/5fdp7bu5yur60fp72tb6.gif" alt="Payment pointer literally becomes read-only" width="718" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Deleting the node will not seem to have any effect.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sxLqJHog--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/z2l6j8fkhdk1wroe7i1f.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sxLqJHog--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/z2l6j8fkhdk1wroe7i1f.gif" alt="Payment pointer cannot be deleted" width="718" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Other payment pointers, if added, will be removed immediately.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eBgugTey--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/63np3xi5g77gmsp1pjhf.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eBgugTey--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/63np3xi5g77gmsp1pjhf.gif" alt="Other payment pointers cannot be added" width="718" height="424"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's available in &lt;a href="https://github.com/chin98edwin/payment-pointer-protector"&gt;this GitHub Repository&lt;/a&gt;. You'll either have to clone or copy from the raw file and add it into your project manually. By the way, I would like to make it into a package and put it up on NPM to make it work like React where people can use it either through &lt;code&gt;unpkg.com&lt;/code&gt; or &lt;code&gt;npm install&lt;/code&gt; but I'm facing some difficulties here. I'm not sure how long it will take me for this to happen, so if you have spare time and energy to help me out, I'll be more than glad.&lt;/p&gt;

&lt;h1&gt;
  
  
  Bottom Line
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;It's possible for people to mess with the payment pointer&lt;/li&gt;
&lt;li&gt;The Payment Pointer Protector is designed to deal with this problem&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But another problem worth thinking about is, should it be up to the developers to deal with this problem? Or perhaps browsers should make an exception to check for the presence of a payment pointer and guard it? &lt;/p&gt;

&lt;p&gt;I can imagine scenarios where people would want to change the payment pointer dynamically. It can be for testing or alternating-interval-based revenue sharing (although &lt;a href="https://webmonetization.org/docs/probabilistic-rev-sharing"&gt;Probabilistic Revenue Sharing&lt;/a&gt; is the recommended way). These things would become impossible and out of our control if it becomes a standard that browsers should automatically guard payment pointers.&lt;/p&gt;

&lt;p&gt;What are your thoughts on this?&lt;/p&gt;

</description>
      <category>html</category>
      <category>webmonetization</category>
      <category>javascript</category>
      <category>paymentpointer</category>
    </item>
    <item>
      <title>Thoughts On What I Have Learned From College</title>
      <dc:creator>GlyphCat</dc:creator>
      <pubDate>Thu, 25 Jun 2020 04:16:22 +0000</pubDate>
      <link>https://dev.to/glyphcat/thoughts-on-what-i-ve-learned-from-college-1jan</link>
      <guid>https://dev.to/glyphcat/thoughts-on-what-i-ve-learned-from-college-1jan</guid>
      <description>&lt;p&gt;A preface question: How much have you learnt from college or through some other traditional education means and to what extent do you find them useful today?&lt;/p&gt;

&lt;p&gt;Let me start with my story.&lt;/p&gt;

&lt;h2&gt;
  
  
  Diploma
&lt;/h2&gt;

&lt;p&gt;I started to learn coding on my own in high school. In diploma, I get to properly learn a few things and they help solidified my basics. I also get to expand my network by making new friends. Great. I was taught some algorithmic thinking, object-oriented programming, HTML &amp;amp; database basics. My self learning was focused on React, React Native, NodeJS, Firebase, npm, things like that.&lt;/p&gt;

&lt;p&gt;There was also an internship but none of the things I learnt so far were relevant to the job scope. I managed to secure my internship position as an iOS software developer probably thanks to my exposure in mobile app development with React Native.&lt;/p&gt;

&lt;h2&gt;
  
  
  Degree
&lt;/h2&gt;

&lt;p&gt;Moving on to degree, not so great. I didn't pick up as much useful skills as before, assignments were stacking up and there was less time to socialize. &lt;/p&gt;

&lt;p&gt;At the same time, I was working part time as a React Native developer for a company. I was exposed to some paid developer tools/APIs that I could not have learn by myself or through college. There was also once I was tasked to add a new feature to a nearly-complete app and straight deploy it to Play Store and App Store. It was a small one tho.&lt;/p&gt;

&lt;p&gt;Then there's another internship. Guess what? Nothing I learnt in college were relevant to this one either. I worked as a web developer (using React and ASP.NET) this time.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Present
&lt;/h2&gt;

&lt;p&gt;This is where I am right now. With two more semesters to go. There's a subject called Agile Development, where we learn how to manage the way we manage things and structure the way we structure things... literally anything but to code with agility. I've been working in three different environments at this point of time and needless to say, I already know how messed up "agile" is. &lt;em&gt;(Disclaimer: it is has its fair share of pros and cons, but most companies today are overhyping it and have mistaken/twisted its concept)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There's also a Final Year Project. None of the things learnt in college were useful enough, my topic was rejected, and the (self-taught) development stack that I proposed for my topic was said to be too simple. Wait, what? So I was never taught anything powerful enough to build a complete and working project, but now I'm suddenly expected to prove what I've learnt by building a flying unicorn and not even my self-taught skills are enough?&lt;/p&gt;


&lt;center&gt;What the meow!&lt;/center&gt;
&lt;br&gt;
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jJhFfWyK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://media2.giphy.com/media/sIIhZliB2McAo/200.gif" alt="Nyan Cat Animation" width="316" height="200"&gt;
&lt;h2&gt;
  
  
  Doubts
&lt;/h2&gt;

&lt;p&gt;I'm having very serious doubts. The only thing I feel like I've learnt in degree is time management and nothing more. Some of my friends are telling me that I should be thankful that my parents can afford to get me into college and I understand that. But at the same time I'm starting have some slight regrets. I could've spared my parents' money. I could've started working or focus on my side projects and make them a thing or do something useful instead of building some superficial unicorn app that's heavily valued from an academic perspective but may not have any value to the real world. &lt;/p&gt;

&lt;p&gt;I studied degree for three reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;I thought it was the norm after graduating from high school (at least in where I live)&lt;/li&gt;
&lt;li&gt;(because of #1) I thought I could improve myself as a developer and feel more secure... 😂&lt;/li&gt;
&lt;li&gt;I was afraid of disappointing my parents&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I'm from an Asian family by the way. My parents never said anything unpleasant to me or forced me, but I know deep down they really want me to get good education, proper certification and have a decent job because they care for me. It would definitely worry them if I suddenly acted different from everyone else. But as time passes I start to realize that this type of certifications are really not for everyone. Most of these certifications just pave way for individual to work for someone else (eg: office work). Just like how a lot of people about my parents' age are living.&lt;/p&gt;

&lt;p&gt;It didn't feel like my confidence increased, nor did I feel more secure when I think about looking for jobs or paying bills. I'm now in that mentality where I'm just scraping by my courses, putting in as little effort as possible into my so called academics and reserving them for my own side projects that I'm certain will be useful to me in the future. There's still a chance they might fail but at least I've tried. I'd rather be happy living a simple life than to earn a boatload of money but living in constant unhappiness.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Can You Take Away from My Story?
&lt;/h2&gt;

&lt;p&gt;People may tell you to at least get a degree, but I ask you to think properly if it's really what you need and if it's going to add value to your future. There are even &lt;a href="https://www.google.com/search?q=elon+musk+degree+not+required"&gt;articles&lt;/a&gt; about Elon Musk saying degree certifications are not necessary.&lt;/p&gt;

&lt;p&gt;It's up to you to decide whether to further your studies or to step out and start working early or do your own things and generate revenue from it. If what you plan to do really needs some sort of certification then by all means go for it, but if you want to get a certification for your someone else's sake or just to feel more secure, then I suggest you to reconsider it. &lt;/p&gt;

&lt;p&gt;After all, life is like driving a car. People can give you directions out of kindness, some can get mad at you for not listening to them, but at the end of the day you're the one in control of the car and if there's a crash, no one is going to be responsible for it except &lt;em&gt;you&lt;/em&gt;.&lt;/p&gt;

</description>
      <category>watercooler</category>
      <category>education</category>
    </item>
  </channel>
</rss>
