<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Sabesan Sathananthan on Medium]]></title>
        <description><![CDATA[Stories by Sabesan Sathananthan on Medium]]></description>
        <link>https://medium.com/@sabesan96?source=rss-b255948cc1f5------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*2dIlbUPGSHNcXVE6D66NaQ@2x.jpeg</url>
            <title>Stories by Sabesan Sathananthan on Medium</title>
            <link>https://medium.com/@sabesan96?source=rss-b255948cc1f5------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 15 Nov 2026 21:18:38 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@sabesan96/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Breaking the Cold Start Barrier]]></title>
            <link>https://medium.com/hacking-hunter/breaking-the-cold-start-barrier-9e00cc34dfae?source=rss-b255948cc1f5------2</link>
            <guid isPermaLink="false">https://medium.com/p/9e00cc34dfae</guid>
            <category><![CDATA[startup]]></category>
            <category><![CDATA[solutions]]></category>
            <category><![CDATA[engineering]]></category>
            <category><![CDATA[entrepreneurship]]></category>
            <category><![CDATA[software-development]]></category>
            <dc:creator><![CDATA[Sabesan Sathananthan]]></dc:creator>
            <pubDate>Fri, 11 Jul 2025 07:13:33 GMT</pubDate>
            <atom:updated>2025-07-11T15:29:34.708Z</atom:updated>
            <content:encoded><![CDATA[<h4>Strategies to Build When You Have No Users</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*o2-IyNGI5hovH9asmTpqlA.png" /><figcaption><a href="https://www.clickmechanic.com/blog/why-wont-my-car-start-in-the-cold/">Source</a></figcaption></figure><p>One of the most critical challenges facing new software products is simple but brutal: when you launch, you have zero users. This phenomenon is known as the <strong>Cold Start problem</strong> — a metaphor derived from trying to start a car in the middle of winter. It’s slow, painful, and likely to fail unless you warm things up fast. This is my 46th Medium article.</p><p>So, how can new software attract users?</p><p>After speaking with several friends who are building startups, one insight stood out: <strong>Cold Start is the number one hurdle</strong> for most founders. It’s often not that hard to build a product — but it’s extremely hard to find users. Solving Cold Start, and sustaining user growth afterward, is the only path to survival and long-term traction.</p><h4>Cracking Cold Start Begins with Network Effects</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*tHa6jHlmOTxDmGmA0wyrDQ.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@frantic?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Alex Kotliarskyi</a> on <a href="https://unsplash.com/photos/people-doing-office-works-QBpZGqEMsKg?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Unsplash</a></figcaption></figure><p>To overcome Cold Start, you must <strong>engineer network effects</strong> into the core of your product.</p><blockquote>So, what are network effects?</blockquote><p>A <strong>network effect</strong> occurs when a product becomes more valuable as more people use it. It’s about turning user connections into retention and stickiness.</p><p>Take the telephone, for example. At launch, it had a Cold Start issue — it could only connect two fixed users, like a glorified walkie-talkie. Naturally, few people wanted it. But once telephone networks formed, adoption skyrocketed. The more users joined, the more valuable the system became.</p><p><strong>In short: your product must enable users to connect with each other</strong> in order to generate compounding value.</p><h4>Start with an Atomic Network</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*tTeyNOumlO7GzRRn4OrlCQ.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@fourcolourblack?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Adam Wilson</a> on <a href="https://unsplash.com/photos/three-peson-sitting-talking-to-each-other-mM7V59F5syw?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Unsplash</a></figcaption></figure><p>When launching a new product, the goal should be to build an <strong>“Atomic Network”</strong> — a small, dense group of users who can extract real value from the network without needing mass adoption.</p><p>An atomic network is the <strong>smallest self-sustaining unit</strong> of your product’s ecosystem — where core interactions are already meaningful.</p><p>Whether you recruit friends, tap into existing communities, or pay users to join, your first milestone should be to <strong>make this initial network functional and engaging from Day One</strong>.</p><h4>Make Sure the Atomic Network Delivers Value in 3 Minutes</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*1VElhFqWj7dcCjyICD1gPA.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@aronvisuals?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Aron Visuals</a> on <a href="https://unsplash.com/photos/selective-focus-photo-of-brown-and-blue-hourglass-on-stones-BXOXnQ26B7o?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Unsplash</a></figcaption></figure><p>Here’s a practical benchmark: the atomic network should offer enough utility that <strong>new users stay engaged for at least 3 minutes</strong>.</p><p>If users drop off before that, it’s a signal that the network density is too weak to deliver value.</p><p>Examples from high-growth platforms:</p><ul><li><strong>Uber</strong>: The atomic network includes 15–20 active drivers in a local area, ensuring a car arrives within 3 minutes.</li><li><strong>Airbnb</strong>: Around 300 active listings per city create enough inventory to attract and retain users.</li><li><strong>Reddit</strong>: 1,000 active subreddits ensure every type of user finds a niche that interests them.</li><li><strong>Slack</strong>: A viable team starts with 3 people and at least 2,000 messages exchanged to demonstrate meaningful collaboration.</li></ul><h4>If Your Product Lacks Network Attributes — Add Them</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*qk3y6Pqnwk0Um4rQKMTMvg.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@parabol?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Parabol | The Agile Meeting Tool</a> on <a href="https://unsplash.com/photos/a-group-of-people-sitting-around-a-wooden-table-CS0D08N2n9M?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Unsplash</a></figcaption></figure><p><strong>Users come for the tools, but stay for the network.</strong></p><p>Instagram started as a basic photo filter app. While initially novel, it failed to retain users — they left after playing with it a few times. The breakthrough came when it evolved into a <strong>photo-sharing social network</strong>, adding the ability to follow others and see real-time photo streams. That shift created the network effect — and led to Instagram’s $1 billion acquisition by Facebook within 18 months.</p><p>Other notable examples:</p><ul><li><strong>Yelp</strong>: Evolved from a simple directory into a review-driven local network.</li><li><strong>LinkedIn</strong>: Transformed from an online résumé builder into a professional networking ecosystem.</li></ul><p><strong>Lesson: </strong><em>If you want network effects, you must become the network.</em></p><h4>The 20,000-User Threshold</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*T6iWD1kbynjQL6eaaw3_mw.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@lukechesser?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Luke Chesser</a> on <a href="https://unsplash.com/photos/graphs-of-performance-analytics-on-a-laptop-screen-JKUTrJ4vK00?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Unsplash</a></figcaption></figure><p>In most market segments, once your product reaches <strong>20,000 active users</strong>, the Cold Start barrier is effectively broken.</p><p>This is the inflection point where the network begins to grow organically, and word-of-mouth kicks in. Once you pass this critical mass, growth becomes exponential and sustainable.</p><h3>Final Thoughts</h3><p>The Cold Start problem isn’t just a technical or marketing challenge — it’s a structural design issue. You must <strong>build your product in a way that creates value for the first 10 users</strong>, not just the first million.</p><p>Focus on atomic networks. Engineer network effects early. And remember: growth is not a feature you add later. It must be embedded from the beginning.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9e00cc34dfae" width="1" height="1" alt=""><hr><p><a href="https://medium.com/hacking-hunter/breaking-the-cold-start-barrier-9e00cc34dfae">Breaking the Cold Start Barrier</a> was originally published in <a href="https://medium.com/hacking-hunter">Hacking Hunter</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Escaping if-else maze in JavaScript]]></title>
            <link>https://javascript.plainenglish.io/escaping-if-else-maze-in-javascript-4d452b831a70?source=rss-b255948cc1f5------2</link>
            <guid isPermaLink="false">https://medium.com/p/4d452b831a70</guid>
            <category><![CDATA[patterns]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[algorithms]]></category>
            <dc:creator><![CDATA[Sabesan Sathananthan]]></dc:creator>
            <pubDate>Thu, 04 Apr 2024 08:17:03 GMT</pubDate>
            <atom:updated>2024-04-04T08:17:03.414Z</atom:updated>
            <content:encoded><![CDATA[<h4>Simplifying JavaScript Logic</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*GhNdQJBshhU_Yst5fgq7lA.jpeg" /><figcaption>source: <a href="https://i1.wp.com/blog.alexdevero.com/wp-content/uploads/2020/06/22-06-20-javascript-if-else-statement-made-simple-blog.jpg?w=1024&amp;ssl=1">link</a></figcaption></figure><p>Typically, many developers easily fall into the if-else trap, not because of the complexity of other solutions, but because it follows the natural language pattern. This is my 45th Medium article. In below, I added the example of multiple if-else spaghetti code.</p><pre>const setColor = (color) =&gt; {<br>    let colorHexCode = &#39;&#39;;<br>    if (color === &#39;blue&#39;) {<br>        colorHexCode = &#39;#4169E1&#39;;<br>    } else if (color === &#39;green&#39;) {<br>        colorHexCode = &#39;#98FF98&#39;;<br>    } else if (color === &#39;butter&#39;) {<br>        colorHexCode = &#39;#FFE4C9&#39;;<br>    } else if (color === &#39;pink&#39;) {<br>        colorHexCode = &#39;#E78895&#39;;<br>    } else {<br>        colorHexCode = &#39;#B4B4B8&#39;;<br>    }<br>    document.getElementById(&#39;button&#39;).style.color = colorHexCode;<br>};</pre><p>Some people may think using a ternary operator helps to escape from the if-else maze.</p><h3>Ternary? Operator:</h3><p>Technically, if-else and ternary serve as conditional operations and the ternary operator is not a revolutionary difference from if-else. The ternary operator returns a value, making it useful for direct value assignment. Below, I added the example of using multiple ternaryoperators.</p><pre>const setColor = (color) =&gt; {<br>  document.getElementById(&#39;button&#39;).style.color =<br>    color === &#39;blue&#39;<br>      ? &#39;#4169E1&#39;<br>      : color === &#39;green&#39;<br>      ? &#39;#98FF98&#39;<br>      : color === &#39;butter&#39;<br>      ? &#39;#FFE4C9&#39;<br>      : color === &#39;pink&#39;<br>      ? &#39;#E78895&#39;<br>      : &#39;#B4B4B8&#39;;<br>};</pre><p>The above example also reduces the readability of the code.</p><h3>Switch() Case:</h3><p>If not using if-else or ternary operator, most developers may go with the switch statement. However, the switch statement entails a significant amount of boilerplate and repetitive code that we could do without.</p><pre>const setColor = (color) =&gt; {<br>  let colorHexCode = &#39;&#39;;<br>  switch (color) {<br>    case &#39;blue&#39;:<br>      colorHexCode = &#39;#4169E1&#39;;<br>      break;<br>    case &#39;green&#39;:<br>      colorHexCode = &#39;#98FF98&#39;;<br>      break;<br>    case &#39;butter&#39;:<br>      colorHexCode = &#39;#FFE4C9&#39;;<br>      break;<br>    case &#39;pink&#39;:<br>      colorHexCode = &#39;#E78895&#39;;<br>      break;<br>    default:<br>      colorHexCode = &#39;#B4B4B8&#39;;<br>  }<br>  document.getElementById(&#39;button&#39;).style.color = colorHexCode;<br>};</pre><h3>Lookup Table</h3><p>The key advantage of using a lookup table over traditional conditional structures like if-else or switch statements is that lookup table turns multiple instances of comparative logic into data.</p><pre>const colorHexCode ={<br>    &#39;blue&#39;: &#39;#4169E1&#39;,<br>    &#39;green&#39;: &#39;#98FF98&#39;,<br>    &#39;butter&#39;: &#39;#FFE4C9&#39;,<br>    &#39;pink&#39;: &#39;#E78895&#39;,<br>    &#39;default&#39;: &#39;#B4B4B8&#39;<br>}<br>const setColor = (color) =&gt; {<br>  let colorHexCode = &#39;&#39;;<br>  document.getElementById(&#39;button&#39;).style.color = colorHexCode[color]? colorHexCode[color]: colorHexCode[&#39;default&#39;];<br>};</pre><p>in the above example, there is only one logic check using a ternary operation for the default fallback.</p><pre>const colorHexCode = {<br>  blue: &#39;#4169E1&#39;,<br>  green: &#39;#98FF98&#39;,<br>  butter: &#39;#FFE4C9&#39;,<br>  pink: &#39;#E78895&#39;,<br>  default: &#39;#B4B4B8&#39;,<br>};<br>const setColor = (color) =&gt; {<br>  let colorHexCode = &#39;&#39;;<br>  document.getElementById(&#39;button&#39;).style.color  = colorHexCode[color] ||  colorHexCode[&#39;default&#39;];<br>};</pre><p>in the above example, there is only one logic check but we avoid ternary operation and use OR operator for the default fallback.</p><p>In the above two examples, the code illustrates the logic as a single operation, making it more expressive. Additionally, the code becomes easier to test due to the minimized logic. By consolidating our comparisons into pure data, we ensure improved maintainability.</p><h3>Conclusion</h3><p>By using a lookup table, the code is cleaner and easy to read and maintain. The average time complexity for the if-else statement, ternary operator, switch statement and lookup table is O(1). There is no difference between the time complexity but the lookup table is a simple pattern and clean.</p><h3>In Plain English 🚀</h3><p><em>Thank you for being a part of the </em><a href="https://plainenglish.io/"><strong><em>In Plain English</em></strong></a><em> community! Before you go:</em></p><ul><li>Be sure to <strong>clap</strong> and <strong>follow</strong> the writer ️👏<strong>️️</strong></li><li>Follow us: <a href="https://twitter.com/inPlainEngHQ"><strong>X</strong></a><strong> | </strong><a href="https://www.linkedin.com/company/inplainenglish/"><strong>LinkedIn</strong></a><strong> | </strong><a href="https://www.youtube.com/channel/UCtipWUghju290NWcn8jhyAw"><strong>YouTube</strong></a><strong> | </strong><a href="https://discord.gg/in-plain-english-709094664682340443"><strong>Discord</strong></a><strong> | </strong><a href="https://newsletter.plainenglish.io/"><strong>Newsletter</strong></a></li><li>Visit our other platforms: <a href="https://stackademic.com/"><strong>Stackademic</strong></a><strong> | </strong><a href="https://cofeed.app/"><strong>CoFeed</strong></a><strong> | </strong><a href="https://venturemagazine.net/"><strong>Venture</strong></a><strong> | </strong><a href="https://blog.cubed.run/"><strong>Cubed</strong></a></li><li>More content at <a href="https://plainenglish.io/"><strong>PlainEnglish.io</strong></a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4d452b831a70" width="1" height="1" alt=""><hr><p><a href="https://javascript.plainenglish.io/escaping-if-else-maze-in-javascript-4d452b831a70">Escaping if-else maze in JavaScript</a> was originally published in <a href="https://javascript.plainenglish.io/">JavaScript in Plain English</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to copy files and folders in Node.js?]]></title>
            <link>https://javascript.plainenglish.io/how-to-copy-files-and-folders-in-node-js-e37394fdf4c0?source=rss-b255948cc1f5------2</link>
            <guid isPermaLink="false">https://medium.com/p/e37394fdf4c0</guid>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[nodejs]]></category>
            <category><![CDATA[linux]]></category>
            <category><![CDATA[node]]></category>
            <category><![CDATA[node-js-tutorial]]></category>
            <dc:creator><![CDATA[Sabesan Sathananthan]]></dc:creator>
            <pubDate>Tue, 27 Dec 2022 12:43:33 GMT</pubDate>
            <atom:updated>2024-07-17T14:50:18.963Z</atom:updated>
            <content:encoded><![CDATA[<h4>Multiple ways to copy files in Node.js</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*7n_qZ-WwSo5EogMXnRc97g.jpeg" /><figcaption>Photo by <a href="https://www.pexels.com/photo/focused-man-writing-in-account-book-at-table-7063776/">Dziana Hasanbekava</a></figcaption></figure><p>In Node.js, there are multiple ways to copy files., let’s take a look at the possible ways and analysis each of them. This is my 44th Medium article.</p><h3>1.copyFile</h3><p>The copyFile() function, which can copy a file directly to the destination directory, performs the simplest action.</p><pre>fs.copyFile(&#39;./data.txt&#39;, &#39;./dest/info.txt&#39;);</pre><blockquote>The above method, asynchronously copies the file from src to dest. If dest is already exists then by default it is overwritten. There are no args passed to the callback function over than any possible exception. Node.js does not ensure that copy operations are atomic. Node.js will attempt to delete the target file if an error happens after opening the target file for writing.</blockquote><p>There is a disadvantage when we use the above method. If the target directory does not exist then an exception will be thrown because the target directory must exist (the method will not automatically create the target directory). Therefore, before using the above method, user must validate whether the target directory definetly exists or not? If the target directory doesn’t exists, user could use fs.mkdir()or fs.mkdirSync()to create the target directory. copyFile() method can’t copy directories.</p><blockquote><em>💡 Speed up your blog creation with </em><a href="https://differ.blog/differ-ai"><strong><em>DifferAI</em></strong></a><em>.</em></blockquote><blockquote><em>Available for </em><strong><em>free </em></strong><em>exclusively on the </em><strong><em>free and open blogging platform, </em></strong><a href="https://differ.blog/"><strong><em>Differ</em></strong></a><strong><em>.</em></strong></blockquote><p><a href="https://differ.blog/differ-ai">Introducing DifferAI</a></p><h3>2. readFile and writeFile</h3><p>In this way, read the content of the source file and then write to the target file. If the content of the source file has to be modified during copying, this method is suitable</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/242f9342601c3aa661ca6f36bb82ad23/href">https://medium.com/media/242f9342601c3aa661ca6f36bb82ad23/href</a></iframe><p>The disadvantage of this method is the same as the above copyFile() method. readFile() method is used to read the contents of the source file and writeFile() method can only write files in existing directories. By using this method we can’t copy directories. The content can be modified while being copied is the advantage of using this method.</p><h3>3. createReadStream and createWriteStream</h3><p>readFile() method and writeFile() method are the whole block of operation data. If the file size is large the above method will put more strain on system resources. createReadStream() and createWriteStream() is to use the way of stream to manipulate data.</p><pre>fs.createReadStream(&#39;./data.txt&#39;).pipe(fs.createWriteStream(`./info.txt`));</pre><h3>4. cp</h3><p>The new <a href="https://nodejs.dev/en/api/v18/fs/#fscpsrc-dest-options-callback">fs.cp()</a> method has been added since version 16.7.0 of Node.js. By using this method, the entire directory structure including subdirectories and files can be copied asynchronously from src to dest. fs.cp() method can copy either a file or a directory. The configuration’s recursive property needs to be set to true if a directory copy is required.</p><h4>To copy files</h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/7c42e257e9c744cbe1e021b5f1ccdb8c/href">https://medium.com/media/7c42e257e9c744cbe1e021b5f1ccdb8c/href</a></iframe><h4>To copy the directory, including subdirectories and files.</h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2512ed6a65129af889614c4d1293af29/href">https://medium.com/media/2512ed6a65129af889614c4d1293af29/href</a></iframe><p>As you can see, this fs.cp() method is much better than the above 3 methods.</p><ol><li>The dest directory doesn’t need to be required to exist. The dest directory will be automatically created if it doesn’t already exist (regardless of the level of a directory)</li><li>You can completely copy files in the entire folder, including subdirectories, without recursively copying them separately.</li></ol><blockquote>When you are going to use this method first thing first you need to confirm the Node.js version!</blockquote><p>What if you want to copy every file in the folder but you only have a lower version of Node.js? We can recursively copy some files in addition to the native cp command for Linux, which is covered in the next section:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9b4c2b791c942415f0c98f1a25dd1327/href">https://medium.com/media/9b4c2b791c942415f0c98f1a25dd1327/href</a></iframe><p>How to use:</p><pre>copyDir(&#39;./component&#39;, &#39;./page/home&#39;);</pre><h3>5. cp command in Linux</h3><p>To execute Linux native commands, we may use the exec or spawn commands in child_process. To copy files or directories, the<a href="https://www.rapidtables.com/code/linux/cp.html"> cp command in Linux</a> is used.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/bc29b004ac5ebe8942bfb14025e0b9cf/href">https://medium.com/media/bc29b004ac5ebe8942bfb14025e0b9cf/href</a></iframe><h3>Conclusion</h3><p>You could able to use the above 5 methods if you are using the latest node version. Using the fs module in the node, I have shared the fastest ways to copy a file/directory. We utterly looked at the asynchronous methods that we accessed through the fs module of Node.js.</p><h3>In Plain English 🚀</h3><p><em>Thank you for being a part of the </em><a href="https://plainenglish.io/"><strong><em>In Plain English</em></strong></a><em> community! Before you go:</em></p><ul><li>Be sure to <strong>clap</strong> and <strong>follow</strong> the writer ️👏<strong>️️</strong></li><li>Follow us: <a href="https://twitter.com/inPlainEngHQ"><strong>X</strong></a> | <a href="https://www.linkedin.com/company/inplainenglish/"><strong>LinkedIn</strong></a> | <a href="https://www.youtube.com/channel/UCtipWUghju290NWcn8jhyAw"><strong>YouTube</strong></a> | <a href="https://discord.gg/in-plain-english-709094664682340443"><strong>Discord</strong></a> | <a href="https://newsletter.plainenglish.io/"><strong>Newsletter</strong></a></li><li>Visit our other platforms: <a href="https://cofeed.app/"><strong>CoFeed</strong></a> | <a href="https://differ.blog/"><strong>Differ</strong></a></li><li>More content at <a href="https://plainenglish.io/"><strong>PlainEnglish.io</strong></a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e37394fdf4c0" width="1" height="1" alt=""><hr><p><a href="https://javascript.plainenglish.io/how-to-copy-files-and-folders-in-node-js-e37394fdf4c0">How to copy files and folders in Node.js?</a> was originally published in <a href="https://javascript.plainenglish.io/">JavaScript in Plain English</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to Override Methods in localStorage?]]></title>
            <link>https://javascript.plainenglish.io/how-to-override-methods-in-localstorage-36c7e5edc47?source=rss-b255948cc1f5------2</link>
            <guid isPermaLink="false">https://medium.com/p/36c7e5edc47</guid>
            <category><![CDATA[localstorage]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[web-design]]></category>
            <dc:creator><![CDATA[Sabesan Sathananthan]]></dc:creator>
            <pubDate>Tue, 06 Sep 2022 14:16:06 GMT</pubDate>
            <atom:updated>2022-09-06T14:16:06.450Z</atom:updated>
            <content:encoded><![CDATA[<h4>Use localStorage with JavaScript.</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*73iHUn-KVVeL6h1HMozCdw.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@melodi2?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Lia Trevarthen</a> on <a href="https://unsplash.com/s/photos/storage?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>I often want to rewrite localStorage to implement a certain function. What are the methods to rewrite the methods in localStorage? There are many developers who want to rewrite the methods in localStorageto realize the expiration time of the key, or to monitor the read and write of the key. So what are the methods to override the methods in localStorage. This is my 43rd Medium article.</p><h3>1. Rewrite directly on localStorage</h3><p>Many developers like the idea of ​​rewriting, first keeping the original method and then rewriting the method directly on localStorage like below.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/880dbc8cc6326c7a1b61ab0df844a049/href">https://medium.com/media/880dbc8cc6326c7a1b61ab0df844a049/href</a></iframe><p>However, this way of writing is not overriding the method setItem(), but to add a setItem attribute to localStorage. When the value attribute of the method is declared, the native setItem() method is overwritten.</p><p>I haven’t tested it too much, but in some browsers, this attribute will be ignored and causing our rewriting to fail.</p><h3>2. Override the method on localStorage.__proto__</h3><p>If we look closely, setItem and getItem are inherited from Storage __proto__ pseudo property.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/706/1*jVpE_3XAF0sjStNWAi7kHA.png" /></figure><p>Then we directly override the above localStorage.__proto__ method.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/bf6efd71e0c7faf5fd417987b20e7f52/href">https://medium.com/media/bf6efd71e0c7faf5fd417987b20e7f52/href</a></iframe><p>This implements the real override of the setItem() method.</p><p>But there is still a problem here. Both localStorage and sessionStorage inherit from <a href="https://developer.mozilla.org/en-US/docs/Web/API/Storage">Storage</a>. After rewriting the properties or methods on localStorage.__proto__, the methods in sessionStorage are also rewritten.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*nmNu0D5zmgtRgICjD2pV0w.png" /></figure><h3>3. External packaging layer</h3><p>We do not directly modify the method of localStorage itself, but wrap a layer on the outside, and then use localStorage to realize the storage function at the bottom layer.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/3a29b8dc3a32f65d00d0649f690b2990/href">https://medium.com/media/3a29b8dc3a32f65d00d0649f690b2990/href</a></iframe><p>In this way, the degree of freedom is relatively higher, and there is no compatibility problem in Section 1. Only the name used has changed and the properties and methods in localStorage are completely blocked.</p><p>If you want to use a custom object without the pack then you need to implement all the properties and methods. It is not possible to mock a method alone like the above.</p><h3>4. Override localStorage</h3><p>Use Object.definePropertyor Proxyequivalent to completely overriding the localStorage variable. Better than Section 3 in that the name has not changed.</p><h4>4.1 Direct coverage, no effect</h4><p>If you use the following method to cover directly, it will have no effect.</p><pre>window.localStorage = Object.create(null);  console.log(window.localStorage); //still native</pre><p>We get the property descriptor of localStorage through <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptor">Object.getOwnPropertyDescriptor</a>. It can be found that there is no writable: true attribute, which means that localStorage is not directly writable.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*yJtgfcwsocxfXDikBb2I6A.png" /></figure><h4>4.2 Overriding with Object.defineProperty</h4><p>Since there is no writableattribute, we will add one to it. We can override localStorage with Object.defineProperty.</p><p>But you can’t use the above writing method with one layer outside. If you directly give the above myLocalStorage to localStorage then it will generate infinite recursion (to avoid misleading, the wrong writing method will not be written here).</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/13ed08853e9def1fb46c47504ac38ba8/href">https://medium.com/media/13ed08853e9def1fb46c47504ac38ba8/href</a></iframe><p>I have made a backup of localStorage here. If you need a native method then you can also operate it.</p><h3>5. Summary</h3><p>In this article, we do not specifically implement a function such as setting the expiration time. But talk about how to rewrite localStorage or the methods in it from another perspective.</p><p><em>More content at </em><a href="https://plainenglish.io/"><strong><em>PlainEnglish.io</em></strong></a><em>. Sign up for our </em><a href="http://newsletter.plainenglish.io/"><strong><em>free weekly newsletter</em></strong></a><em>. Follow us on </em><a href="https://twitter.com/inPlainEngHQ"><strong><em>Twitter</em></strong></a>, <a href="https://www.linkedin.com/company/inplainenglish/"><strong><em>LinkedIn</em></strong></a><em>, </em><a href="https://www.youtube.com/channel/UCtipWUghju290NWcn8jhyAw"><strong><em>YouTube</em></strong></a><em>, and </em><a href="https://discord.gg/GtDtUAvyhW"><strong><em>Discord</em></strong></a><em>.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=36c7e5edc47" width="1" height="1" alt=""><hr><p><a href="https://javascript.plainenglish.io/how-to-override-methods-in-localstorage-36c7e5edc47">How to Override Methods in localStorage?</a> was originally published in <a href="https://javascript.plainenglish.io/">JavaScript in Plain English</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[What Are Microservices?]]></title>
            <link>https://aws.plainenglish.io/what-are-microservices-606ce04c5a01?source=rss-b255948cc1f5------2</link>
            <guid isPermaLink="false">https://medium.com/p/606ce04c5a01</guid>
            <category><![CDATA[architecture]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[microservices]]></category>
            <category><![CDATA[app-development]]></category>
            <category><![CDATA[technology]]></category>
            <dc:creator><![CDATA[Sabesan Sathananthan]]></dc:creator>
            <pubDate>Wed, 03 Aug 2022 16:17:30 GMT</pubDate>
            <atom:updated>2022-08-03T16:17:30.024Z</atom:updated>
            <content:encoded><![CDATA[<h4>Microservices are a type of software architecture that is gaining popularity.</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*k5GUBax6BYrRMA4JrloWzA.jpeg" /><figcaption>Photo by <a href="https://www.pexels.com/photo/man-wearing-face-mask-standing-near-vehicle-door-with-brown-carton-boxes-6407541/">Pavel Danilyuk</a></figcaption></figure><p>What does the term “microservices” mean exactly? What sort of architecture falls within the microservices? Despite the abundance of materials online, none of them are easy for beginners to understand. In my opinion, this concept is actually rather straightforward and is easily explainable. Nowadays, developers need to do changes to an application and need to deploy it as soon as possible without redeploying the whole application. This problem led to the microservices development paradigm. This is my 42nd Medium article.</p><h3>Monolithic software</h3><p>You must first understand the development of software architecture in understanding microservices. Software that had all functionalities created at once was known as <strong>monolithic</strong> software in the early days of software development. Like an integrated machine, the entire piece of software exists as one unit.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*XwGUIeRZ9pEmBAIqzl4XPA.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@zoltantasi?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Zoltan Tasi</a> on <a href="https://unsplash.com/s/photos/monolith?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>In the monolithic architecture, it is conceivable that the more functions of the software will be the more complex and many shortcomings will be exposed.</p><ol><li>All functions are coupled together, affect each other, and are ultimately difficult to manage.</li><li>Even if only one line of code is modified, the entire software must be rebuilt and deployed, which is very costly.</li><li>Because the software is made into a whole, it is impossible for each function to be developed and tested separately, but only as a whole, so the waterfall development model must be adopted.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*tpttJOxS6faMKqeaK708kg.png" /></figure><p>In short, large-scale software with monolithic architecture is not only slow to develop but also forms complex code that is difficult to maintain and upgrade and becomes a heavy burden for programmers.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/541/1*W4i85DXYvEPyhKPeQ--CBg.png" /></figure><h3>Service-Oriented Architecture</h3><p>It has long been suggested that the monolithic architecture must be divided, the coupling of the code must be broken, and the program should be divided into independent functional units in order to address the aforementioned issues. The term “service-oriented architecture” (SOA) first appeared about 20 years ago, when functional units could be provided remotely as “services”.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*hR5woU_kw1v5Q5_222O0bQ.png" /></figure><p>Software that continually performs a certain function in the background is known as a service. The most popular service is the Web service, which offers external web access through port 80.</p><p>“Service-Oriented Architecture” is to split a single large program into independent services like smaller programs. The services are connected by communication protocols and each service is a separate, independently operating entity that performs various tasks.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/750/1*aPAetSmTJDnSw7CNFnPEow.png" /></figure><p>This architecture has many advantages. Those are,</p><ol><li>Each service has a single function which is equivalent to a small software and convenient for development and testing.</li><li>Each service runs independently, which simplifies the architecture and improves reliability.</li><li>The same service might be used for multiple purposes, therefore encouraging and supporting code reuse.</li><li>For easy upgrades, different services can be developed and deployed independently.</li><li>Good scalability, simple addition of more machines and functionalities, and capacity to bear heavy loads</li><li>Less probability to have a single point of failure because a service won’t affect by another service’s failures.</li></ol><p>Language is not a factor in service-oriented design, as opposed to monolithic architecture. Different services may need to be deployed in various environments and systems, and they may be built using various languages and tools. This indicates that the <strong>service-oriented architecture operates on several servers by default</strong>, each of which offers a service, and the combination of numerous servers creates a full-fledged network application.</p><h3>Microservices</h3><p>Microservices design focuses on categorizing programs that are otherwise huge and cumbersome. Each microservice is focused on a certain feature or function of an application. Several of these microservices are combined to make a single, efficient application.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2vnYR0vuuh4rVzzYLeCRcw.png" /></figure><p>This instinctive, functional split of an application has a lot of advantages. The user interface can be used by the client to make requests. Simultaneously, one or more microservices are engaged to accomplish the desired operation via the API gateway.</p><h4>Advantages of Microservices Architecture</h4><p>In application development using microservice architecture is a beneficial approach. <strong>A microservice is an independent </strong>process<strong>. </strong>This process can run locally, on another server, or in the cloud (such as cloud services and cloud function FaaS). Its characteristics are the same as service-oriented architecture, but because it is lighter, the decoupling and service-oriented functions can be done more thoroughly. Also, it can be standardized, the same container will have the same result no matter where it is run, so there are many SaaS products on the market that provide standardized microservices.</p><ul><li><strong>Scaling up requires less development work.</strong></li></ul><p>As microservices are self-contained, smaller development teams may work on different components simultaneously to update current functionality. This makes it much easier to not just discover and scale hot services independently of the rest of the app, but also to enhance the app as a whole.</p><ul><li><strong>Independent deployment</strong></li></ul><p>Each microservice setups a full-stack application. At any point, microservices are to be deployed independently. It’s simple for development teams to work on one microservice to solve bugs and then redeploy it without redeploying the entire application because microservices are granular in nature.</p><ul><li><strong>improved fault isolation</strong></li></ul><p>Even a minor component failure might render the entire application inoperable in a monolithic application. Determining the mistake can occasionally be time-consuming. Since the entire program is separated into independent, fully functional software components, identifying the problematic component is simple when using microservices. Other unrelated units will still work even if errors happen.</p><ul><li><strong>No reliance on a single tech stack</strong></li></ul><p>A set of programming languages, front-end and back-end tools, frameworks, databases, and other similar elements are collectively referred to as a technological stack and are used by developers to create applications. Developers can choose a technology stack with microservices that is most suited for a certain microservice and its functions.</p><p>Microservice architecture accelerates and optimizes software development. Agile deployment aptness combined with flexible application of various technologies significantly reduces the development cycle duration. Microservices architecture is used for <strong>data processing tasks, media content</strong> (ie. Netflix, Amazon Prime),<strong> website migration, handling transactions and generating invoices</strong>.</p><p>Docker, which debuted in 2014, completely changed how software is developed. It enables program containerization, uses a minimal amount of system resources, and lets each container create its own operating environment.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*T4T1ZmRDRkY_ZpAKH25NPg.png" /></figure><p>Evidently, “service-oriented architecture” can be implemented using containers, and each service now resides in a container rather on a server. Multiple servers are not required in this method. To construct a service-oriented architecture, which was previously impossible, the system runs several containers in the most basic scenario. Microservices are the name of this implementation. Microservices are <strong>service-oriented architectures that make use of container technology</strong>. Although it still uses “service” as a functional unit, the implementation is now lightweight, just requiring a new container (a process), thus the term “microservice”.</p><h4>Challenges in microservice</h4><p>From deployment through operation and maintenance, the microservices architecture has its share of difficulties. Some of the hurdles are discussed below.</p><ul><li><strong>Inter-service communication</strong></li></ul><p>A microservice frequently need to communicate and interact with another microservice to meet certain demands or complete particular tasks. This demand maintains a fully functional API providing a channel of communication between various services making up the application.</p><ul><li><strong>Distributed logging</strong></li></ul><p>When many microservices are implemented as a component of an application, each of these services has a unique logging method. As a result, there are significant amounts of dispersed log data that are unstructured and challenging to manage.</p><ul><li><strong>spanning transactions</strong></li></ul><p>Distributed transactions are those that need a number of microservices to be deployed and operating correctly in order to complete. This implies that a transaction involves several microservices and databases, and it will fail if even a little error is in just one of them.</p><ul><li><strong>Cyclic dependencies</strong></li></ul><p>In a microservices architecture, codependency between two or more application services or modules is referred to as a cyclic dependency. It may be challenging to grow the application or separately deploy and manage microservices due to cyclical dependencies. Additionally, they are notorious for making code harder to maintain. Decoupling becomes very hard if they continue for a while.</p><h3>Conclusion</h3><p>The most widely used and trustworthy method for creating cloud applications nowadays is the microservices architecture. It has strong support because of the many benefits it offers tech development teams, including faster development times, increased flexibility, and higher reliability.</p><p><em>More content at </em><a href="https://plainenglish.io/"><strong><em>PlainEnglish.io</em></strong></a><em>. Sign up for our </em><a href="http://newsletter.plainenglish.io/"><strong><em>free weekly newsletter</em></strong></a><em>. Follow us on </em><a href="https://twitter.com/inPlainEngHQ"><strong><em>Twitter</em></strong></a>, <a href="https://www.linkedin.com/company/inplainenglish/"><strong><em>LinkedIn</em></strong></a>,<em> and</em><strong><em> </em></strong><a href="https://discord.gg/GtDtUAvyhW"><strong><em>Discord</em></strong></a><em>.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=606ce04c5a01" width="1" height="1" alt=""><hr><p><a href="https://aws.plainenglish.io/what-are-microservices-606ce04c5a01">What Are Microservices?</a> was originally published in <a href="https://aws.plainenglish.io/">AWS in Plain English</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The Medium RSS Feed’s Missing Part]]></title>
            <link>https://medium.com/geekculture/the-medium-rss-feeds-missing-part-65a0b556dda1?source=rss-b255948cc1f5------2</link>
            <guid isPermaLink="false">https://medium.com/p/65a0b556dda1</guid>
            <category><![CDATA[scraping]]></category>
            <category><![CDATA[medium]]></category>
            <category><![CDATA[api]]></category>
            <category><![CDATA[nodejs]]></category>
            <category><![CDATA[expressjs]]></category>
            <dc:creator><![CDATA[Sabesan Sathananthan]]></dc:creator>
            <pubDate>Fri, 03 Jun 2022 10:32:55 GMT</pubDate>
            <atom:updated>2022-06-03T10:32:55.597Z</atom:updated>
            <content:encoded><![CDATA[<h4>retrieves the stats (clapCount, voterCount, responseCount, and readingTime) of Medium posts</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*nln9J0e0JIij-vLu9nBWvg.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@ryoji__iwata?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Ryoji Iwata</a> on <a href="https://unsplash.com/s/photos/puzzle-missing-pieces?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>In this article, I will explain how to retrieve the stats ( claps count, voter count, response count, and reading time) of Medium feed posts using a REST API, the lack of this feature in the Medium RSS feed is what motivated me to create this advanced Medium API. This is my 41st Medium article.</p><h3>Initial Intuition</h3><blockquote>I wanted to obtain the stats ( <em>claps count</em>, <em>voter count</em>, <em>response count</em>, and <em>reading time</em>) of my Medium posts while working on my personal website development. 2 years before when I implement the medium widget to my website I found <a href="https://medium-widget.pixelpoint.io/">Pixelpoint.io</a> which generated a widget with clap counts of a medium post. At that moment I wondered how they implemented it? Then I forget to research it but last month I found that pixelpoint.io’s widget is not working. I looked everywhere for a solution to my needs but couldn’t find one, so I had no choice but to code it myself.</blockquote><p>My initial intuition was to look at the RSS feed but there were no such details are provided then I looked at the official documentation of the public <a href="https://github.com/Medium/medium-api-docs">REST API</a> by Medium, and nothing was there either. The Medium REST API only allows you to create a Medium article by HTTP POST method(cf<a href="https://github.com/Medium/medium-api-docs#33-posts"> section 3.3</a>). <em>You can’t retrieve or edit a Medium article by using the Medium API 😔.</em></p><p>In order to get an understanding of how the useful stats are retrieved in the Medium post, I started to inspect the Medium using browser developer tools. Shockingly, there was no request to obtain the stats among all the XHR calls, which push me to look at the HTML response of the Medium post.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*iK-81Yo7eR8z55mOJoXAow.png" /><figcaption>Inspecting a Medium post page.</figcaption></figure><pre>curl <a href="https://medium.com/p/unique_Id_of_the_post">https://medium.com/p/unique_Id_of_the_post</a> &gt;&gt; post.html</pre><p>As a javascript variable, the claps count, voter count, response count, and reading time are directly injected into the HTML response. You can verify that by typing console.log(window.__APOLLO_STATE__); in the Javascript console of the Post page.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*1yjiDqp1gbUtEcpCh5wbQQ.png" /><figcaption>window.__APOLLO_STATE__ object</figcaption></figure><p>Then I scrape those useful stats using <a href="https://github.com/request/request">request</a> and <a href="https://cheerio.js.org/">cheerio</a> .</p><h3>How to scrape data in Script Tag</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*BWZQVQ3VD9uh6LVboW-E8w.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@kikesalazarn?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Kike Salazar N</a> on <a href="https://unsplash.com/s/photos/scrape?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>In a medium post, data comes as JSON in a script tag. By using javascript, those data are picked up and rendered in DOM on the browser-side. Usually, data in a script tag takes this form:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/ec3ceb318aeebbb8045647b77cec49c1/href">https://medium.com/media/ec3ceb318aeebbb8045647b77cec49c1/href</a></iframe><p>Then I scrape Medium post data without a headless browser.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/3dad5342e13f9fae28b34508c8b55b1c/href">https://medium.com/media/3dad5342e13f9fae28b34508c8b55b1c/href</a></iframe><p>First, I get the website and look for errors. Then I confirmed whether the body exists, and load the body using cheerio in $ . In try block, all the tag script contents are mapped in an array. Then find the element which includes window.__APOLLO_STATE__ , replace the assignment window.__APOLLO_STATE__ = with an empty string. I replace the /&amp;quot;/g with ‘&quot;’ and parse with JSON.parse . Finally, get the appropriate values from the JSON.</p><p>The advantages of this technique over headless browsers are super fast and takes way less processing and resources.</p><h3>How to use the Advanced Medium API</h3><p>You could able to use the <a href="https://github.com/sabesansathananthan/advanced-medium-api/tree/develop">Advanced Medium API</a> that I developed as follows:</p><p>There are 5 types of requests. you could be able to get all the responses by using HTTP GETmethod.</p><h4>Medium feed in JSON</h4><p>You could able to get the RSS feed of the last 10 Medium posts by using the following links (replace your username instead of @username ).</p><pre><em>medium.com/feed/@username <br></em>or<em> <br>username.medium.com/feed</em></pre><p>The following request of the API gives the direct JSON conversion of that RSS Feed.</p><pre>curl <a href="https://advanced-medium-api.herokuapp.com/medium/user/%7BuserId%7D">https://advanced-medium-api.herokuapp.com/medium/user/{userId}</a></pre><h4>Medium Advanced Data</h4><p>You could able to get the Medium feed in JSON with the missing part of the Medium feed such as clapCount, voterCount, responseCount, readingTime. each missing data injected in every post(items) object.</p><p>The following request of the API gives the JSON conversion of the RSS feed with the injection of missing data.</p><pre>curl <a href="https://advanced-medium-api.herokuapp.com/advanced/user/%7BuserId%7D">https://advanced-medium-api.herokuapp.com/advanced/user/{userId}</a></pre><h4>Medium Customized Data</h4><p>JSON conversion of the Medium RSS feed is customized according to the categories. Order the Medium post’s tags according to their use count among the latest 10 posts and the tagOrder return that tags&#39; order rank. Medium&#39;s latest 10 posts were divided by 3 and every 3 posts were pushed in an array and those arrays were pushed in one array. There is an algorithm that returns the most suitable tag for the Medium post among the other tags of that Medium post.</p><p>The following request of the API gives the customized version of the Medium feed in JSON</p><pre>curl <a href="https://advanced-medium-api.herokuapp.com/customized/user/%7BuserId%7D">https://advanced-medium-api.herokuapp.com/customized/user/{userId}</a></pre><h4>Medium Customized Advanced Data</h4><p>This response contains the Medium customized data with the injection of missing stats such as clapCount, voterCount, responseCount, readingTime.</p><p>The following request of the API gives the customized version of the Medium feed in JSON with the missing part of the Medium feed.</p><pre>curl <a href="https://advanced-medium-api.herokuapp.com/advanced/customized/user/%7BuserId%7D">https://advanced-medium-api.herokuapp.com/advanced/customized/user/{userId}</a></pre><h4>Missing data of a particular post.</h4><p>This response contains only the missing part (clapCount, voterCount, responseCount, readingTime) of Medium feed for a particular Medium post.</p><p><strong>Request </strong>💻 ➡ 🌎<strong> :</strong></p><pre>curl <a href="https://advanced-medium-api.herokuapp.com/medium/post/%7BpostId%7D">https://advanced-medium-api.herokuapp.com/medium/post/{postId}</a></pre><p><strong>Response </strong>🌎➡💻 :</p><pre>{<br>  &quot;clapCount&quot;: 98,<br>  &quot;responseCount&quot;: 4,<br>  &quot;voterCount&quot;: 12,<br>  &quot;readingTime&quot;: 4<br>}</pre><h3>Conclusion</h3><p>This API is <a href="https://github.com/sabesansathananthan/advanced-medium-api">Open Source</a> and I welcome your contributions. last 2 years I used the medium widget from <a href="https://medium-widget.pixelpoint.io/">Pixelpoint.io</a> which generated a widget with clap counts of a medium post. I didn’t do research to get the missing part of the Medium feed when I used Pixelpoint.io. but 2 months before Pixelpoint.io is not working and this incident affects my personal website. Therefore I pushed myself and created this API.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=65a0b556dda1" width="1" height="1" alt=""><hr><p><a href="https://medium.com/geekculture/the-medium-rss-feeds-missing-part-65a0b556dda1">The Medium RSS Feed’s Missing Part</a> was originally published in <a href="https://medium.com/geekculture">Geek Culture</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Why and How to Use Absolute Imports in React]]></title>
            <link>https://javascript.plainenglish.io/why-and-how-to-use-absolute-imports-in-react-d5b52f24d53c?source=rss-b255948cc1f5------2</link>
            <guid isPermaLink="false">https://medium.com/p/d5b52f24d53c</guid>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[react]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[front-end-development]]></category>
            <category><![CDATA[programming]]></category>
            <dc:creator><![CDATA[Sabesan Sathananthan]]></dc:creator>
            <pubDate>Fri, 08 Oct 2021 10:45:44 GMT</pubDate>
            <atom:updated>2021-10-08T11:30:31.084Z</atom:updated>
            <content:encoded><![CDATA[<h4>Front End</h4><h4>An easy way to maintain clean code in React</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*jgQN6rI0OJB_OXgVTgOwLw.jpeg" /><figcaption>Photo by <a href="https://www.pexels.com/@ketut-subiyanto?utm_content=attributionCopyText&amp;utm_medium=referral&amp;utm_source=pexels">Ketut Subiyanto</a> from <a href="https://www.pexels.com/photo/crop-faceless-man-packing-box-with-scotch-tape-4246109/?utm_content=attributionCopyText&amp;utm_medium=referral&amp;utm_source=pexels">Pexels</a></figcaption></figure><p>Using absolute imports to better organize your React project is a great way. Relative imports are hard to follow and break during refactoring. Absolute imports manage your project easier as it grows. Forget long relative imports after this article. This is my 40th Medium article.</p><h3>The Problem</h3><p>What if your project’s folder structure is complex, and you need to <strong>go up</strong> in it? Inside of your components, you have imports that look like the below example with relative imports.</p><pre>import {MyComponent} from ‘../../../../components/MyComponent’;</pre><p>You can break the above import by changing the path of the component from which you are importing your MyComponent. Let’s assume you decide to move MyComponent into its own folder. Then you would need to update all of your imports in your project and add one extra ../ to all of your imports. Relative imports has some more problems.</p><ul><li>Pretty hard to refactor</li><li>It becomes worse as you get further deeper into it.</li><li>You need to change the entire codebase if you need to extract the code to be used externally as an NPM module.</li></ul><h3>Absolute Imports</h3><p>By using absolute imports, you can alias some folders to a name like below:</p><pre>import {MyComponent} from ‘components/MyComponent’;</pre><p>Absolute imports have some advantages.</p><ul><li>There is no ../../../../hell. Therefore easier to type out the imports.</li><li>Easily copy-paste the code with imports into another file in the project and not have to tinker with import paths.</li><li>It is short and sweet</li></ul><p>The below example is a file with Relative imports.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/bf07582509895a0421291b5c22db5b93/href">https://medium.com/media/bf07582509895a0421291b5c22db5b93/href</a></iframe><p>Make the imports in the above file prettier.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f50a23cf68a84b3a75257aca796260ae/href">https://medium.com/media/f50a23cf68a84b3a75257aca796260ae/href</a></iframe><p>Therefore, how can you use absolute imports with ReactJs?</p><h4>Using TypeScript</h4><p>If you need to set up absolute imports in your Typescript application add/update your tsconfig.json file in the root directory of the project. Then you need to update the compiler option baseUrl in the file.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/94d143b8d97ef92279a8442c500e4c56/href">https://medium.com/media/94d143b8d97ef92279a8442c500e4c56/href</a></iframe><h4>Using JavaScript</h4><p>Setting up absolute imports to Typescript and setting up absolute imports to JavaScript is pretty much the same process. Create the jsconfig.json file in the root directory of the project. Then you need to update the following snippet.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b900ae2e75d9c9321443dfe726867272/href">https://medium.com/media/b900ae2e75d9c9321443dfe726867272/href</a></iframe><p>Now you can import your components like this.</p><pre>import {MyComponent} from ‘components/MyComponent’;</pre><p>You can also use the compiler option paths as well. Perhaps you want to alias your component folder. For that, you need to set up your tsconfig.json, or jsconfig.json as shown in below:</p><pre>{<br>  &quot;compilerOptions&quot;: {<br>    &quot;baseUrl&quot;: &quot;./&quot;,<br>    &quot;paths&quot;: {<br>      &quot;@component/*&quot;: [&quot;src/components/*&quot;],<br>    }<br>  }<br>}</pre><p>Now you can import the components from your component folder like this:</p><pre>import {MyComponent} from ‘@component/MyComponent’;</pre><p>is that enough?</p><p>Well, no… You need to make your IDE smart to understand absolute imports in your files. Here I am going to mention the progress for the top 2 IDEs. Those are VS Code and WebStrom.</p><h4>For VS Code</h4><p>VS Code is smart enough to understand the tsconfig.json, or jsconfig.json file. Intellisense and jump-to-source are just working fine with absolute imports.</p><p>Therefore, you can follow the above process.</p><h4>For WebStrom / IntelliJ Idea</h4><p>Select the src folder in the project window and right-click on it. Select the option <strong>Mark Directory as</strong> and then select the <strong>Resources Root</strong> option.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/744/1*1QCjtXr7W8tAS97Etkna_w.png" /></figure><p>Now go to <strong>Settings</strong> -&gt; <strong>Editor -</strong>&gt; <strong>Code Style</strong> -&gt; <strong>JavaScript </strong>and<strong> </strong>select the <strong>Imports</strong> tab. Then check the <strong>Use paths relative to the project, resource or sources roots</strong>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*VhExpM1Kx5SaHMvuIyAeHg.png" /></figure><p>Now WebStrom knows where the absolute imports are pointing. There won’t no warnings and autocomplete/ jump-to-source will work. This means the auto-import mechanism uses absolute imports.</p><p>If you are a strict developer like me, use something like Airbnb’s ESLint config.</p><h4>With ESLint</h4><p>Create React App also has an ESLint setup but it has a minimal set of rules. <a href="https://github.com/benmosher/eslint-plugin-import">eslint-plugin-import</a> is used by Airbnb and this plugin checks undefined imports. When you are going to use Airbnb’s ESLint config it will give you the error shown below:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/592/1*7w-nu2REGmEs3V4-1dNcXw.png" /></figure><p>You can fix the error by add settings prop in your ESLint config. That setting prop point that your imports might be relative to src folder. Therefore, you need to add update your ESLint config in .eslintrc file like this:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d608ef6ca698cb7586d1e89fb901eecf/href">https://medium.com/media/d608ef6ca698cb7586d1e89fb901eecf/href</a></iframe><p>You don’t need to install any NPM modules to avoid the ESLint error, add the settings prop is enough.</p><h4>By Convention</h4><p>Absolute imports have been possible for a long time with Webpack. When you are naming your aliased folder, you need to use PascalCase/CamelCase because it is the convention follow in the <a href="https://webpack.js.org/configuration/resolve/#resolvealias">Webpack</a>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/1*SsTWqQeNRLM8ReY5PBPK8w.png" /></figure><h3>Conclusion</h3><p>Absolute imports might befuddle a new developer for a while. If they understand it, then it is pretty easy to use. Therefore, I suggest including a few lines about importing mechanisms in your Readme, or you might link to this article. I am not going to change any content after I publish this article. I hope you enjoyed this small trick to better organize your React project.</p><p>Have fun coding! 😃</p><p><em>More content at </em><a href="http://plainenglish.io/"><strong><em>plainenglish.io</em></strong></a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d5b52f24d53c" width="1" height="1" alt=""><hr><p><a href="https://javascript.plainenglish.io/why-and-how-to-use-absolute-imports-in-react-d5b52f24d53c">Why and How to Use Absolute Imports in React</a> was originally published in <a href="https://javascript.plainenglish.io/">JavaScript in Plain English</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to mock network request in Jest]]></title>
            <link>https://medium.com/geekculture/how-to-mock-network-request-in-jest-40958bb8d8e2?source=rss-b255948cc1f5------2</link>
            <guid isPermaLink="false">https://medium.com/p/40958bb8d8e2</guid>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[jest]]></category>
            <category><![CDATA[unit-testing]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[testing]]></category>
            <dc:creator><![CDATA[Sabesan Sathananthan]]></dc:creator>
            <pubDate>Sun, 03 Oct 2021 20:32:09 GMT</pubDate>
            <atom:updated>2021-10-03T20:32:09.622Z</atom:updated>
            <content:encoded><![CDATA[<h4>TESTING</h4><h4>Mocking network requests even easier</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*poXRRZdZAElrrP9C3ZQLoQ.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@tvick?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Taylor Vick</a> on <a href="https://unsplash.com/@tvick?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>Nowadays, it is necessary to modify an older library to TS and perform unit testing. If the library is modified to TS, there is still a little bit better. Unit testing is purely a current study and sold now. For beginners to learn the Jest framework, I think the more troublesome thing in unit testing is to test network requests. So record some of the ways that Mock dropped Axios to initiate network requests. This is my 39th Medium article.</p><h3>Introduction</h3><p>The examples mentioned in the article are all in the <a href="https://github.com/sabesansathananthan/jest-mock-server">jest-mock-server</a> repository. You can start the example directly by installing the package manager, for example, installing through yarn:</p><pre>$ yarn install</pre><p>Some commands are specified in the package.json, which are as follows:</p><ul><li>npm run build : The packaging command of rollup .</li><li>npm run test:demo1 : Simply mock the network request library encapsulated.</li><li>npm run test:demo2 : Complete the mock by re-implement hook.</li><li>npm run test:demo3 : Use the library in Jest to complete the implementation of demo2.</li><li>npm run test:demo4-5 : Start a node server, proxy the network request through the proxy of axios, and forward it to the started node server. By setting the corresponding unit test request and response data, the corresponding relationship is used to realize the test, which is jest-mock-server finished work.</li></ul><p>Here we encapsulate a layer of axios, which is closer to the real scene. You can view the test/demo/wrap-request.ts file. In fact, it simply creates an axios instance internally and forwards the response data.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/189a99f308e1f40a89b298507ec69d60/href">https://medium.com/media/189a99f308e1f40a89b298507ec69d60/href</a></iframe><p>The test/demo/index.ts file simply exports a counter method, where these two parameters are processed to a certain extent before the network request is initiated. Then the response data is also processed to a certain extent, just to simulate related operations.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2c1f8febcb377b42bd7bab7d64ed57e8/href">https://medium.com/media/2c1f8febcb377b42bd7bab7d64ed57e8/href</a></iframe><p>Here Jest uses the browser environment simulated by JSDOM, the startup file test/config/setup.js is configured in the setupFiles attribute configured in jest.config.js, and JSDOM is initialized here.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/62edd6ebce331fbd8fbd0c1f8bba461e/href">https://medium.com/media/62edd6ebce331fbd8fbd0c1f8bba461e/href</a></iframe><h3>demo1: Simple Mock network request</h3><p>Simple mock processing is performed in test/demo1.test.js, and you can try to run it through npm run test:demo1. In fact, a mock operation is performed on the wrap-request library that wraps axios. wrap-request will be compiled when Jest is started. After the library is mocked here, all the files imported into the library afterward will get the mocked objects. In other words, we can think that this library has been rewritten, and the methods after rewriting are all JEST’s Mock Functions . You can use functions such as mockReturnValue for data simulation. For Mock Functions, please refer to this <a href="https://www.jestjs.cn/docs/mock-functions">link</a>.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/5cad0c513dca3ae373ff71e603280117/href">https://medium.com/media/5cad0c513dca3ae373ff71e603280117/href</a></iframe><p>Here we have completed the Mock of the return value, which means that we can control the value returned by the request in the wrap-request library. However, it was mentioned before that there are also certain processes for the incoming parameters. We haven’t made any assertions on this part of the content, so we also need to try to deal with this.</p><h3>demo2: hook network request</h3><p>demo2 can be tried to run through npm run test:demo2. As mentioned above, we can handle the return value but there is no way to assert whether the input parameters are processed correctly so we need to deal with this situation. Fortunately, Jest provides a way to directly implement the function library that is mocked. Therefore, Jest also provides a mockImplementation method, which is used in demo3. Here we have rewritten the mocked function library. We can also use jest.fn to complete Implementations . Here we write a hook function before returning and then implement assertions or specify return values ​​in each test. In this way, the above problem can be solved, which is actually the realization of mockImplementation of Mock Functionsin Jest.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/55e00636b422895a42181b3e57fc4f48/href">https://medium.com/media/55e00636b422895a42181b3e57fc4f48/href</a></iframe><h3>demo3: Use Jest’s mockImplementation</h3><p>demo3 can be tried to run through npm run test:demo3. The example in demo2 is actually complicated to write. In Jest, Mock Functionshas the implementation of mockImplementation which can be used directly.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/ca006cc73a21e00c49fa70a4026c7764/href">https://medium.com/media/ca006cc73a21e00c49fa70a4026c7764/href</a></iframe><h3>demo4–5: Really initiate a network request</h3><p>demo4 and demo5 can be tried to run through npm run test:demo4–5. In this way, a real data request is made. Here, axios proxy will be used to forward internal data requests to the specified server port. Therefore, the server is also started locally and the test is performed by specifying the request and response data related to the corresponding path. If the requested data is incorrect then the related response data will not be matched normally. Therefore, the request will directly return 500. If the returned response data is incorrect, it will also be captured during the assertion. In the jest-mock-server library, first, we need to specify three files which are corresponding to the three life cycles that each unit test file to be executed before startup. Jest test is executed before the three life cycles and the three life cycles are executed after the Jest test is completed. The three files which we need to specify are the setupFiles, globalSetup, and globalTeardown configuration items of the jest.config.js configuration file.</p><p>First we are going to start with setupFiles. In addition to initializing JSDOM, we also need to operate the default proxy of axios. Because the solution adopted is to use the proxy of axios to forward data requests. Therefore, it is necessary to set the proxy value at the forefront of the unit test.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9b4cb805078f7a02e4b544bd746591e2/href">https://medium.com/media/9b4cb805078f7a02e4b544bd746591e2/href</a></iframe><p>Once we set up the above file inside thetest/config folder then we need to add two more files in there which are globalSetup and globalTeardown . These two files refer to the operations performed before the Jest unit test starts and after all tests are completed. We put the server startup and shutdown operations in those two files.</p><blockquote>Please note that the file running in these two files is a separate independent <em>contex</em> which has nothing to do with the <em>contex</em> of any unit test including the file specified by the setupFiles configuration item. Therefore, all the data here is either specified in the configuration file, or It is to transmit between server ports through the network.</blockquote><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/3b08699d87ba11d0f53387fc5861f153/href">https://medium.com/media/3b08699d87ba11d0f53387fc5861f153/href</a></iframe><p>For the configuration port and domain name information, put it directly in the globals field in jest.config.js. For the debug configuration item, it is recommended to use it in conjunction with test.only.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9257d7afd40ae230f49809ec06859a58/href">https://medium.com/media/9257d7afd40ae230f49809ec06859a58/href</a></iframe><p>Now, there may be suggestion that why the server should not be started and shut down in the beforeAll and afterAll life cycles of each unit test file. Therefore, I have tried this solution. In this solution, for each test file, the server is started and then shut down. Therefore, this solution is relatively time-consuming. But in theory, this solution is reasonable. After all, it is true that data isolation is necessary. But there is a problem when afterAll is closed. It does not actually close the server and port occupation because the close method is called when the node server is closed. WhenafterAll is closed, It just stopped processing the request but the port is still occupied. When the second unit test file is started, an exception will be thrown that the port is being used. Although I tried some solutions, they are not ideal because sometimes the port is still occupied. Especially when the node is run for the first time after it is turned on, the probability of abnormality is relatively high. Therefore, the effect is not very satisfactory. In the end, the complete isolation scheme is adopted. For specific related issues, please refer to this <a href="https://stackoverflow.com/questions/14626636/how-do-i-shutdown-a-node-js-https-server-immediately">link</a>.</p><p>Since we adopt a completely isolated solution, there are only two options when we want to transmit the request and response data for the test request. The two solutions are either when the server is started all the data is specified in the test/config/global-setup.js file or the data is transmitted through the network when the server is running, the path is specified and the network request of the path will carry data and the data request will be specified in the closure of the server. Therefore, both options are supported here. I think it is more appropriate to specify your own data in each unit test file, so here is only one example of specifying the data to be tested in the unit test file. Regarding the data to be tested, a DataMapper type is specified to reduce exceptions caused by type errors. Therefore, two data sets are exemplified here. In addition, regular expressions are supported when matching query and data. The structure of the DataMapper type is relatively standard.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/49d069f721d4cff024b11b03333415db/href">https://medium.com/media/49d069f721d4cff024b11b03333415db/href</a></iframe><p>In the below two unit tests, the data to be tested is specified in beforeAll. Note that beforeAll is return setSuitesData(data) because the unit test is executed after the data is set and the response is successful, followed by the normal request and response whether the assertion test is correct.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/ea84a68a6c5934e5c6806b48a265edf8/href">https://medium.com/media/ea84a68a6c5934e5c6806b48a265edf8/href</a></iframe><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=40958bb8d8e2" width="1" height="1" alt=""><hr><p><a href="https://medium.com/geekculture/how-to-mock-network-request-in-jest-40958bb8d8e2">How to mock network request in Jest</a> was originally published in <a href="https://medium.com/geekculture">Geek Culture</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How To Reuse React Components]]></title>
            <link>https://medium.com/codezillas/how-to-reuse-react-components-851ffcc68a9c?source=rss-b255948cc1f5------2</link>
            <guid isPermaLink="false">https://medium.com/p/851ffcc68a9c</guid>
            <category><![CDATA[front-end-development]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[react]]></category>
            <category><![CDATA[web-development]]></category>
            <dc:creator><![CDATA[Sabesan Sathananthan]]></dc:creator>
            <pubDate>Thu, 24 Jun 2021 15:25:34 GMT</pubDate>
            <atom:updated>2021-06-24T15:34:27.299Z</atom:updated>
            <content:encoded><![CDATA[<h4>Mixins, HOC, render props, and Hooks are four ways to reuse components</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*HvyPiGMOis-_Gxp6cyttiA.jpeg" /><figcaption>Photo by <a href="https://www.pexels.com/@vlada-karpovich?utm_content=attributionCopyText&amp;utm_medium=referral&amp;utm_source=pexels">Vlada Karpovich</a> from <a href="https://www.pexels.com/photo/photo-of-pen-beside-ink-4668356/?utm_content=attributionCopyText&amp;utm_medium=referral&amp;utm_source=pexels">Pexels</a></figcaption></figure><p>Now frontend engineering is more and more important. Although Ctrl+C and Ctrl+V can also be used to complete requirements, once they are modified, it becomes a huge task. Therefore, copying of code is reduced, and the packaging and reuse capabilities are increased to achieve maintainability and reversibility. The code used becomes particularly important.</p><p>In React, components are the main unit of code reuse. The combination-based component reuse mechanism is quite elegant, but for more fine-grained logic (state logic, behavior logic, etc.), reuse is not so easy. It is difficult to disassemble the state logic as a reusable function or component. In fact, before the appearance of Hooks, there was a lack of a simple and direct way of component behavior extension, which is considered to be mixins, higher-order components (HOC), and render props. The upper-level model explored under the existing (component mechanism) game rules has not solved the problem of logic reuse between components from the root. This is my 38th Medium article.</p><h3>Mixins</h3><p>Of course, React no longer recommends using mixins as a reuse solution for a long time, but it can still provide support for mixins through create-react-class. Note that mixins are not supported when declaring components in ES6 classes.</p><p>Mixins allow multiple React components to share code. They are very similar to mixins in Python or traits in PHP. The emergence of the mixin solution comes from an OOP intuition. In the early days, it only provided React.createClass() API to define components. (In React v15.5.0, it is officially abandoned and moved to create-react-class). Naturally, (class) inheritance has become an intuitive attempt, and in JavaScript prototype-based extension mode, it is similar to the inherited mixin scheme. It has become a good solution. Mixin is mainly used to solve the reuse problem of life cycle logic and state logic, and allows the component life cycle to be extended from the outside. This is especially important in Flux and other modes, but many defects have also appeared in continuous practice:</p><ul><li>There is an implicit dependency between the component and the mixin (Mixin often depends on the specific method of the component, but the dependency is not known when the component is defined).</li><li>There may be conflicts between multiple mixin (such as defining the same state field).</li><li>Mixin tends to add more states, which reduces the predictability of the application and leads to a sharp increase in complexity.</li><li>Implicit dependencies lead to opaque dependencies, and maintenance costs and understanding costs are rising rapidly.</li><li>It is difficult to quickly understand the behavior of components, and it is necessary to fully understand all the extension behaviors that rely on mixin and their mutual influence.</li><li>The method and state field of the component itself is afraid to be easily deleted because it is difficult to determine whether mixin depends on it.</li><li>Mixin is also difficult to maintain, because Mixin logic will eventually be flattened and merged together, and it is difficult to figure out the input and output of a Mixin.</li></ul><p>There is no doubt that these problems are fatal, so Reactv0.13.0 abandoned Mixin static crosscutting (similar to inherited reuse) and moved to HOC higher-order components (similar to combined reuse).</p><h4>Example</h4><p>The example of the ancient version, a common scenario is: A component needs to be updated regularly. It is easy to do it with setInterval(), but it is very important to cancel the timer when it is not needed to save memory. React provides a lifecycle method to inform the component. The time of creation or destruction, the following Mixin, use setInterval() and ensure that the timer is cleaned up when the component is destroyed.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/6fd5344ded564231f982182c4310121b/href">https://medium.com/media/6fd5344ded564231f982182c4310121b/href</a></iframe><h3>HOC</h3><p>After Mixin, HOC high-order components take on the heavy responsibility and become the recommended solution for logical reuse between components. High-order components reveal a high-order atmosphere from their names. In fact, this concept should be derived from high-order functions of JavaScript. The high-order function is a function that accepts a function as input or output. It can be thought that currying is a higher-order function. The definition of higher-order components is also given in the React document. Higher-order components receive components and return new components. function. The specific meaning is: High-order components can be seen as an implementation of React decoration pattern. High-order components are a function, and the function accepts a component as a parameter and returns a new component. It will return an enhanced React components. High-order components can make our code more reusable, logical and abstract, can hijack the render method, and can also control propsand state.</p><p>Comparing Mixin and HOC, Mixin is a mixed-in mode. In actual use, Mixin is still very powerful, allowing us to share the same method in multiple components, but it will also continue to add new methods and attributes to the components. The component itself can not only perceive but also need to do related processing (such as naming conflicts, state maintenance, etc.). Once the mixed modules increase, the entire component becomes difficult to maintain. Mixin may introduce invisible attributes, such as in the Mixin method used in the rendering component brings invisible property props and states to the component. Mixin may depend on each other and is coupled with each other, which is not conducive to code maintenance. In addition, the methods in different Mixin may conflict with each other. Previously React officially recommended using Mixin to solve problems related to cross-cutting concerns, but because using Mixin may cause more trouble, the official recommendation is now to use HOC. High-order component HOC belong to the idea of ​​ functional programming. The wrapped components will not be aware of the existence of high-order components, and the components returned by high-order components will have a functional enhancement effect on the original components. Based on this, React officially recommends the use of high-order components.</p><p>Although HOC does not have so many fatal problems, it also has some minor flaws:</p><ul><li>Scalability restriction: HOC cannot completely replace Mixin. In some scenarios, Mixin can but HOC cannot. For example, PureRenderMixin, because HOC cannot access the State of subcomponents from the outside, and at the same time filter out unnecessary updates through shouldComponentUpdate. Therefore, React After supporting ES6Class, React.PureComponent is provided to solve this problem.</li><li>Ref transfer problem: Ref is cut off. The transfer problem of Ref is quite annoying under the layers of packaging. The function Ref can alleviate part of it (allowing HOC to learn about node creation and destruction), so the React.forwardRef API API was introduced later.</li><li>WrapperHell: HOC is flooded, and WrapperHell appears (there is no problem that cannot be solved by one layer, if there is, then two layers). Multi-layer abstraction also increases complexity and cost of understanding. This is the most critical defect. In HOC mode There is no good solution.</li></ul><h4>Example</h4><p>Specifically, a high-order component is a function whose parameter is a component and the return value is a new component. A component converts props into a UI but a high-order component converts a component into another component. HOC is very common in React third-party libraries, such as Redux’s connect and Relay’s createFragmentContainer.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/90068090af75d82f09618a2e3b129735/href">https://medium.com/media/90068090af75d82f09618a2e3b129735/href</a></iframe><p>Attention should be paid here, do not try to modify the component prototype in the HOC in any way, but should use the combination method to realize the function by packaging the component in the container component. Under normal circumstances, there are two ways to implement high-order components:</p><ul><li>Property agent Props Proxy.</li><li>Reverse inheritance Inheritance Inversion.</li></ul><h4>Property Agent</h4><p>For example, we can add a stored id attribute value to the incoming component. We can add a props to this component through high-order components. Of course, we can also operate on the props in the WrappedComponent component in JSX. Note that it is not to manipulate the incoming WrappedComponent class, we should not directly modify the incoming component, but can operate on it in the process of combination.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/49e24540e51916b4fb3de4aaabb24ed1/href">https://medium.com/media/49e24540e51916b4fb3de4aaabb24ed1/href</a></iframe><p>We can also use high-order components to load the state of new components into the packaged components. For example, we can use high-order components to convert uncontrolled components into controlled components.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c21c2997d27e3522421b423881bfa3a3/href">https://medium.com/media/c21c2997d27e3522421b423881bfa3a3/href</a></iframe><p>Or our purpose is to wrap it with other components to achieve the purpose of layout or style.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a67368bf8f443f35fa16cb084dd3581b/href">https://medium.com/media/a67368bf8f443f35fa16cb084dd3581b/href</a></iframe><h4>Reverse inheritance</h4><p>Reverse inheritance means that the returned component inherits the previous component. In reverse inheritance, we can do a lot of operations, modify state, props and even flip the Element Tree. There is an important point in the reverse inheritance that reverse inheritance cannot ensure that the complete sub-component tree is parsed. That means if the parsed element tree contains components (function type or Class type), the sub-components of the component can no longer be manipulated.</p><p>When we use reverse inheritance to implement high-order components, we can control rendering through rendering hijacking. Specifically, we can consciously control the rendering process of WrappedComponent to control the results of rendering control. For example, we can decide whether to render components according to some parameters.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2f51f1a2e79f2d530f865980dba2158b/href">https://medium.com/media/2f51f1a2e79f2d530f865980dba2158b/href</a></iframe><p>We can even hijack the life cycle of the original component by rewriting.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d0d1d1a2e3655228e9e6214117d3fa91/href">https://medium.com/media/d0d1d1a2e3655228e9e6214117d3fa91/href</a></iframe><p>Since it is actually an inheritance relationship, we can read the props and state of the component. If necessary, we can even add, modify, and delete the props and state. Of course, the premise is that the risks caused by the modification need to be controlled by yourself. In some cases, we may need to pass in some parameters for the high-order attributes, then we can pass in the parameters in the form of currying, and cooperate with the high-order components to complete the operation similar to the closure of the component.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c93764203e66ee528fa2590b469fe091/href">https://medium.com/media/c93764203e66ee528fa2590b469fe091/href</a></iframe><h4>note</h4><p><strong>Don’t change the original components</strong></p><p>Don’t try to modify the component prototype in HOC, or change it in other ways.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/38ab4b11e2b2e2bd581eca1ce0cfc6e6/href">https://medium.com/media/38ab4b11e2b2e2bd581eca1ce0cfc6e6/href</a></iframe><p>Doing so will have some undesirable consequences. One is that the input component can no longer be used as before the HOC enhancement. What is more serious is that if you use another HOC that also modifies componentDidUpdate to enhance it, the previous HOC will be invalid, and this HOC cannot be applied to functional components that have no life cycle.<br>Modifying the HOC of the incoming component is a bad abstraction, and the caller must know how they are implemented to avoid conflicts with other HOC. HOC should not modify the incoming components, but should use a combination of components to achieve functions by packaging the components in container components.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9d539457779e7022762037d655c757e3/href">https://medium.com/media/9d539457779e7022762037d655c757e3/href</a></iframe><p><strong>Filter props</strong></p><p>HOC adds features to components and should not significantly change the convention itself. The components returned by HOC should maintain similar interfaces with the original components. HOC should transparently transmit props that have nothing to do with itself, and most HOC should include a render method similar to the following.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/674a9a7a926cee12af9dbd9e6423db36/href">https://medium.com/media/674a9a7a926cee12af9dbd9e6423db36/href</a></iframe><p><strong>Maximum composability</strong></p><p>Not all HOCs are the same. Sometimes it only accepts one parameter, which is the packaged component.</p><pre>const NavbarWithRouter = withRouter(Navbar);</pre><p>HOC can usually receive multiple parameters. For example, in Relay, HOC additionally receives a configuration object to specify the data dependency of the component.</p><pre>const CommentWithRelay = Relay.createContainer(Comment, config);</pre><p>The most common HOC signatures are as follows, connect is a higher-order function that returns higher-order components.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/590de18c82ad90e07cf1f8fed23a9845/href">https://medium.com/media/590de18c82ad90e07cf1f8fed23a9845/href</a></iframe><p>This form may seem confusing or unnecessary, but it has a useful property, like the single-parameter HOC returned by the connect function has the signature Component =&gt; Component , and functions with the same output type and input type can be easily combined. The same attributes also allow connect and other HOCs to assume the role of decorator. In addition, many third-party libraries provide compose tool functions, including lodash, Redux, and Ramda.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9cbc152eb50e35834c4d012ba48bfdbe/href">https://medium.com/media/9cbc152eb50e35834c4d012ba48bfdbe/href</a></iframe><p><strong>Don’t use HOC in the render method</strong></p><p>React ’s diff algorithm uses the component identifier to determine whether it should update the existing subtree or discard it and mount the new subtree. If the component returned from the render is the same as the component in the previous render ===, React passes The subtree is distinguished from the new subtree to recursively update the subtree, and if they are not equal, the previous subtree is completely unloaded.<br>Usually, you don’t need to consider this when using it, but it is very important for HOC, because it means that you should not apply HOC to a component in the render method of the component.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/01ec9da706301817b5d6ae40a4748a33/href">https://medium.com/media/01ec9da706301817b5d6ae40a4748a33/href</a></iframe><p>This is not just a performance issue. Re-mounting the component will cause the state of the component and all its subcomponents to be lost. If the HOC is created outside the component, the component will only be created once. So every time you render it will be the same component. Generally speaking, this is consistent with your expected performance. In rare cases, you need to call HOC dynamically, you can call it in the component’s lifecycle method or its constructor.</p><p><strong>Be sure to copy static methods</strong></p><p>Sometimes it is useful to define static methods on React components. For example, the Relay container exposes a static method getFragment to facilitate the composition of GraphQL fragments. But when you apply HOC to a component, the original component will be packaged with a container component, which means that the new component does not have any static methods of the original component.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/efea68083923fe3dd728247948db447f/href">https://medium.com/media/efea68083923fe3dd728247948db447f/href</a></iframe><p>To solve this problem, you can copy these methods to the container component before returning.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9abac726b9373ce25fce08cf13c3fc22/href">https://medium.com/media/9abac726b9373ce25fce08cf13c3fc22/href</a></iframe><p>But to do this, you need to know which methods should be copied. You can use hoist-non-react-statics to automatically copy all non-React static methods.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/791281382a5f23b7de315432be7c3aab/href">https://medium.com/media/791281382a5f23b7de315432be7c3aab/href</a></iframe><p>In addition to exporting components, another feasible solution is to additionally export this static method.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/3d9ffdbc5203c4e03a2864d4b6ceadcb/href">https://medium.com/media/3d9ffdbc5203c4e03a2864d4b6ceadcb/href</a></iframe><p><strong>Refs will not be passed</strong></p><p>Although the convention of high-level components is to pass all props to the packaged component, this does not apply to refs, because ref is not actually a prop, just like a key, it is specifically handled by React. If the ref is added to the return component of the HOC, the ref reference points to the container component, not the packaged component. This problem can be explicitly forwarded to the internal component through the React.forwardRefAPI refs.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b2badf123b0fde8ea364b52fc69fb78c/href">https://medium.com/media/b2badf123b0fde8ea364b52fc69fb78c/href</a></iframe><h3>Render Props</h3><p>Like HOC, Render props is also a veteran model that has always existed. render props refers to a simple technology that uses a props valued as a function to share code between a kind of React components. A component with render props receives a function. This function Return a React element and call it instead of implementing its own rendering logic. Render props is a function props used to tell the component what content needs to be rendered. It is also a way to implement component logic reuse. Simply put, it is being copied. In the component used, pass a prop property named render (the property name may not render, as long as the value is a function). The property is a function. This function accepts an object and returns a subcomponent, which will The object in the function parameter is passed as props to the newly generated component, and when using the caller component, you only need to decide where to renderthe component and what logic to renderand pass in the relevant object.<br>Comparing HOC and Render props, technically, both are based on the component combination mechanism. Render props has the same extensibility as HOC. It is called Render props. It does not mean that it can only be used to reuse rendering logic, but that it is here. In this mode, the components are combined through render(), similar to the establishment of a combination relationship through Wrapper’s render() in HOC mode. The two are very similar, and they will also produce a layer of Wrapper. In fact, Render props and HOC . It can even be converted to each other.<br>Similarly, Render props will have some problems:</p><ul><li>The data flow is more intuitive. The descendant components can clearly see the source of the data, but in essence, Render props is implemented based on closures. A large number of component reuse will inevitably introduce the callback hell problem.</li><li>The context of the component is lost, so there is no this.propsproperty, and this.props.childern cannot be accessed like HOC.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/64a91bfecbecd6c5b4769f5780282dbb/href">https://medium.com/media/64a91bfecbecd6c5b4769f5780282dbb/href</a></iframe><h3>Hooks</h3><p>There are endless code reuse solutions, but overall code reuse is still very complicated. A large part of this is because fine-grained code reuse should not be bundled with component reuse. HOC, Render props, etc. are based on component combination The solution is equivalent to first packaging the logic to be reused into components, and then using the component reuse mechanism to achieve logic reuse. Naturally, it is limited to component reuse, so there are problems such as limited scalability, Ref partition, Wrapper Hell, etc. , Then we need to have a simple and direct way of code reuse. Functions. Separating reusable logic into functions should be the most direct and cost-effective way of code reuse. But for state logic, some abstract patterns are still needed. (Such as Observable) can be reused, which is exactly the idea of ​​Hooks, using functions as the smallest code reuse unit, and built-in some modes to simplify the reuse of state logic. Compared with the other solutions mentioned above, Hooks makes the logic reuse within the component no longer bundled with the component reuse. It is really trying to solve the problem of fine-grained logic reuse (between components) from the lower level. In addition, this statement The modular logic reuse scheme further extends the explicit data flow and combination ideas between components to the components.<br>File Hooks are not perfect either, but for now, its disadvantages are as follows:</p><ul><li>The additional learning cost mainly lies in the comparison between Functional Component and Class Component .</li><li>There are restrictions on the writing method (cannot appear in conditions, loops), and the writing restrictions increase the cost of reconstruction.</li><li>It destroys the performance optimization effect of PureComponent and React.memo shallow comparison. In order to get the latest props and state, the event function must be recreated every render()</li><li>In closure scenarios, old state and props values may be referenced.</li><li>The internal implementation is not intuitive, relying on a mutable global state, and no longer so pure.</li><li>React.memo can’t completely replace shouldComponentUpdate (because state change is not available, only for props change).</li><li>The useStateAPI is not perfect in design.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/6b1308a30a4cc6f973b8276a25aec06d/href">https://medium.com/media/6b1308a30a4cc6f973b8276a25aec06d/href</a></iframe><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=851ffcc68a9c" width="1" height="1" alt=""><hr><p><a href="https://medium.com/codezillas/how-to-reuse-react-components-851ffcc68a9c">How To Reuse React Components</a> was originally published in <a href="https://medium.com/codezillas">Codezillas</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Explore Clipboard Operation in JavaScript]]></title>
            <link>https://medium.com/geekculture/explore-clipboard-operation-in-javascript-c6399619c0ac?source=rss-b255948cc1f5------2</link>
            <guid isPermaLink="false">https://medium.com/p/c6399619c0ac</guid>
            <category><![CDATA[javascript-tips]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[development]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[technology]]></category>
            <dc:creator><![CDATA[Sabesan Sathananthan]]></dc:creator>
            <pubDate>Mon, 22 Mar 2021 08:02:38 GMT</pubDate>
            <atom:updated>2021-03-22T08:02:38.418Z</atom:updated>
            <content:encoded><![CDATA[<h4>Cut, Copy and Paste in JavaScript</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*5NqK_GvOb0buWsDmDUvWkg.jpeg" /><figcaption>Photo by <a href="https://www.pexels.com/@alex-green?utm_content=attributionCopyText&amp;utm_medium=referral&amp;utm_source=pexels">Alex Green</a> from <a href="https://www.pexels.com/photo/crop-interviewer-writing-in-notepad-and-talking-to-job-seeker-5699480/?utm_content=attributionCopyText&amp;utm_medium=referral&amp;utm_source=pexels">Pexels</a></figcaption></figure><p>The browser allows JavaScript scripts to read and write to the clipboard, and automatically copy or paste content. In general, scripts should not modify the user’s clipboard, so as not to meet the user’s expectations. However, sometimes it can be convenient to do this, such as the “one-click copy” function, the user clicks a button, and the specified content is automatically entered into the clipboard. Currently, there are three ways to implement clipboard operations.</p><ul><li>Document.execCommand()method</li><li>Asynchronous Clipboard API</li><li>copy,cut and paste Events</li></ul><p>This article introduces these three methods one by one. This is my 37th Medium article.</p><h3>Document.execCommand() method</h3><p>Document.execCommand() is the traditional method of manipulating the clipboard, which is supported by various browsers. It supports the three operations of copy, cut, and paste.</p><ul><li>Document.execCommand(&#39;copy&#39;) — copy</li><li>Document.execCommand(&#39;cut&#39;) — cut</li><li>Document.execCommand(&#39;paste&#39;) — paste</li></ul><h4>Copy or Cut operation</h4><p>When copying, first select the text and then call the Document.execCommand(&#39;copy&#39;), the selected text will enter the clipboard.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9d3d2c9d872794a6960dac276cdafef3/href">https://medium.com/media/9d3d2c9d872794a6960dac276cdafef3/href</a></iframe><p>In the above example, the script first selects the text in the inputElement of the input box ( inputElement.select() ), and then Document.execCommand(&#39;copy&#39;) copies it to the clipboard. Note that the copy operation is best placed in the event listener function, triggered by the user (for example, the user clicks a button). If the script is executed autonomously, some browsers may report an error. Cut operation is also similar to the copy operation.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2c370cdc565840fc90b9b2d114951405/href">https://medium.com/media/2c370cdc565840fc90b9b2d114951405/href</a></iframe><h4>Paste operation</h4><p>When pasting, calling Document.execCommand(&#39;paste&#39;) will output the contents of the clipboard to the current focus element.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/87c5e442a7018036dfc607514de7c9af/href">https://medium.com/media/87c5e442a7018036dfc607514de7c9af/href</a></iframe><h4>Disadvantage</h4><p>Although the Document.execCommand() method is convenient, it has some disadvantages. First, it can only copy the selected content to the clipboard, and cannot write content to the clipboard arbitrarily. Secondly, it is an asynchronous operation. If you copy/paste a large amount of data, the page will freeze. Some browsers will also pop up a prompt box and ask the user for permission. At this time, the page will become unresponsive before the user makes a choice. In order to solve these problems, browser vendors have proposed an asynchronous Clipboard API.</p><h3>Asynchronous Clipboard API</h3><p>Clipboard API is the next-generation clipboard operation method, which is more powerful and reasonable than the traditional Document.execCommand() method. All its operations are asynchronous and return Promise objects without causing page jams. Moreover, it can put arbitrary content (such as pictures) into the clipboard. The navigator.clipboard property returns the Clipboard object, and all operations are performed through this object.</p><pre>const clipboardObj = navigator.clipboard;</pre><p>If the navigator.clipboard property returns undefined, it means that the current browser does not support this API (you can see the full compatibly table on <a href="https://caniuse.com/async-clipboard">Can I use</a>…). Since users may put sensitive data (such as passwords) on the clipboard, allowing scripts to read them arbitrarily will cause security risks, so this API has more security restrictions. First of all, the Chrome browser stipulates that only HTTPS protocol pages can use this API. However, the development environment (localhost) allows the use of non-encrypted protocols. Secondly, the user’s permission needs to be clearly obtained when calling. The specific implementation of permissions uses the Permissions API. There are two permissions related to the clipboard: clipboard-write (write permission) and clipboard-read (read permission). The “write permission” is automatically granted to the script, and the “read permission” must be explicitly granted by the user. In other words, the script can be automatically completed when writing to the clipboard, but when reading the clipboard, the browser will pop up a dialog box asking whether the user agrees to read.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/810/1*fmmX3ymNeN4iSPfG8UU1QA.png" /><figcaption>The permission prompt for the Clipboard API.</figcaption></figure><p>In addition, it should be noted that what the script reads is always the clipboard of the current page. One problem that this brings is that if you paste the relevant code into the developer tool and run it directly, an error may be reported because the current page at this time is the window of the developer tool, not a web page.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c917e180df44ce0caf0e422b013fb7c6/href">https://medium.com/media/c917e180df44ce0caf0e422b013fb7c6/href</a></iframe><p>If you paste the above code into the developer tool and run it, an error will be reported. Because when the code is running, the developer tool window is the current page, and there is no DOM interface that the Clipboard API depends on this page. One solution is to put the relevant code in setTimeout() to delay running, and quickly click on the page window of the browser before calling the function to turn it into the current page.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d4a86d5bd7042b55a12b262e7de204b8/href">https://medium.com/media/d4a86d5bd7042b55a12b262e7de204b8/href</a></iframe><p>After the above code is pasted into the developer tool to run, quickly click on the page window of the webpage to make it the current page, so that no error will be reported.</p><h4>Clipboard object</h4><p><strong>clipboard.readText()</strong></p><p>The clipboard.readText() method is used to copy the text data in the clipboard.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/edbdd6afe11db16aef6fd8cf2a5de380/href">https://medium.com/media/edbdd6afe11db16aef6fd8cf2a5de380/href</a></iframe><p>In the above example, after the user clicks on the page, the text in the clipboard will be output. Note that the browser will pop up a dialog box at this time, asking the user whether to agree with the script to read the clipboard.</p><p>If the user disagrees, the script will report an error. At this time, you can use the try...catch structure to handle errors.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/7c30cda146134fe78fac02686240a822/href">https://medium.com/media/7c30cda146134fe78fac02686240a822/href</a></iframe><p><strong>clipboard.read()</strong></p><p>The clipboard.read() method is used to copy the data in the clipboard, which can be text data or binary data (such as pictures). This method requires explicit permission from the user. This method returns a Promise object. Once the state of the object becomes resolved, an array can be obtained, and each array member is an instance of a ClipboardItem object.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/5cfc2aab31a340fb24537d54448883e5/href">https://medium.com/media/5cfc2aab31a340fb24537d54448883e5/href</a></iframe><p>The ClipboardItem object represents a single clip item and each clip item has a clipboardItem.types property and a clipboardItem.getType() method. The clipboardItem.types property returns an array whose members are the MIME types available for the clip item. For example, a clip item can be pasted in HTML format or in plain text format. Then it has two MIME types (text/html and text/plain). The clipboardItem.getType(type) method is used to read the data of the clip item and returns a Promise object. This method accepts the MIME type of the clip item as a parameter and returns the data of that type. This parameter is required, otherwise, an error will be reported.</p><p><strong>clipboard.writeText()</strong></p><p>The clipboard.writeText() method is used to write text content to the clipboard.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b2786f780145c34da1d8d8b5f9970b7a/href">https://medium.com/media/b2786f780145c34da1d8d8b5f9970b7a/href</a></iframe><p>The above example is that after the user clicks on the web page, the script writes text data to the clipboard. This method does not require user permission, but it is best to put it in try...catch to prevent errors.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/5b8e90947eaf99a062e9f43615c2fb1d/href">https://medium.com/media/5b8e90947eaf99a062e9f43615c2fb1d/href</a></iframe><p><strong>clipboard.write()</strong></p><p>The clipboard.write() method is used to write arbitrary data to the clipboard, which can be text data or binary data. This method accepts a ClipboardItem instance as a parameter, which represents the data written to the clipboard.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/1e4d8b9a0faa7aa9e8a6e4b84bd23a91/href">https://medium.com/media/1e4d8b9a0faa7aa9e8a6e4b84bd23a91/href</a></iframe><p>In the above example, the script writes a picture to the clipboard. Note that the Chrome browser currently (until this writer writes this article) only supports writing images in PNG format. clipboardItem() is a constructor natively provided by the browser to generate an instance of clipboardItem. It accepts an object as a parameter. The key name of the object is the MIME type of the data, and the key value is the data itself. The following example is to write the value of the same clip item in multiple formats to the clipboard, one is text data, and the other is binary data for pasting on different occasions.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/4f89456ef61ba1676c74565508e34724/href">https://medium.com/media/4f89456ef61ba1676c74565508e34724/href</a></iframe><h3>Copy, Cut, and Paste Events</h3><p>When the user puts data into the clipboard, the copy event will be triggered. The following example is to convert the text that the user puts on the clipboard to uppercase.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/56349f2db4f9a0c68d50bfbd1e7b8e7d/href">https://medium.com/media/56349f2db4f9a0c68d50bfbd1e7b8e7d/href</a></iframe><p>In the above example, the clipboardData property of the event object contains the clipboard data. It is an object with the following properties and methods.</p><ul><li>Event.clipboardData.setData(type, data) : To modify the clipboard data, you need to specify the data type.</li><li>Event.clipboardData.getData(type) : To obtain clipboard data, you need to specify the data type.</li><li>Event.clipboardData.clearData([type]) : Clear clipboard data, you can specify the data type. If you do not specify the type, all types of data will be cleared.</li><li>Event.clipboardData.items : An array-like object contains all clip items, but usually there is only one clip item</li></ul><p>The following example is to intercept the user’s copy operation and put the specified content into the clipboard.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/4c39a1a4f6b3efcf4b47960f1f287627/href">https://medium.com/media/4c39a1a4f6b3efcf4b47960f1f287627/href</a></iframe><p>In the above example, first, use e.preventDefault() to cancel the default operation of the clipboard, and then the script takes over the copy operation. The cut event is triggered when the user performs a cutting operation. Its processing is exactly the same as the copy event, and the cut data is also obtained from the Event.clipboardData property.</p><p>When the user uses the clipboard data to paste, the paste event will be triggered. The following example is to intercept the paste operation, the data in the clipboard is taken out by the script.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/6aab8e207fccce5d7e966d382c2050b0/href">https://medium.com/media/6aab8e207fccce5d7e966d382c2050b0/href</a></iframe><h3>Conclusion</h3><p>For user experience, Clipboard access is a great tool. But Clipboard access has its thorns. Some users bring malicious data and some users carry sensitive data. Make sure you handle other user’s data responsibly. You need to prepare yourself for those nasty paste events.</p><p>Asynchronous Clipboard API is new, and no browser supports all features, but it’s easier to use and more robust than the old Document.execCommand() method.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c6399619c0ac" width="1" height="1" alt=""><hr><p><a href="https://medium.com/geekculture/explore-clipboard-operation-in-javascript-c6399619c0ac">Explore Clipboard Operation in JavaScript</a> was originally published in <a href="https://medium.com/geekculture">Geek Culture</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>