<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ghaleb</title>
    <description>The latest articles on DEV Community by Ghaleb (@ghamadi).</description>
    <link>https://dev.to/ghamadi</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F289131%2Fc53d1ed7-cd31-4809-92d1-1cc780b38a49.png</url>
      <title>DEV Community: Ghaleb</title>
      <link>https://dev.to/ghamadi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ghamadi"/>
    <language>en</language>
    <item>
      <title>Rethinking Password Strength Estimation: Beyond Composition Rules</title>
      <dc:creator>Ghaleb</dc:creator>
      <pubDate>Sun, 15 Oct 2023 15:21:49 +0000</pubDate>
      <link>https://dev.to/ghamadi/rethinking-password-strength-estimation-beyond-composition-rules-408i</link>
      <guid>https://dev.to/ghamadi/rethinking-password-strength-estimation-beyond-composition-rules-408i</guid>
      <description>&lt;p&gt;Although many systems are incorporating various authentication mechanisms that replace or complement the traditional username/password approach, passwords remain at the center of internet security today. And the best way to guarantee a password's strength is to guarantee that it is long enough and random enough that brute-forcing it becomes extremely difficult.&lt;/p&gt;

&lt;p&gt;Achieving optimal randomness often necessitates the use of password generators. However, while strategies like the &lt;a href="https://en.wikipedia.org/wiki/Diceware"&gt;Diceware method&lt;/a&gt; help, computer-generated passwords can be difficult to remember and require the use of password managers which many users opt out of.&lt;/p&gt;

&lt;p&gt;Thus, for users, understanding and following best practices is crucial to ensure a password's resilience. Concurrently, for developers, strength meters serve as a defensive measure ensuring that users don't jeopardize system security with easily crackable passwords.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Shortcomings of Composition Rules
&lt;/h2&gt;

&lt;p&gt;According to the &lt;a href="https://pages.nist.gov/800-63-3/sp800-63b.html#appA"&gt;NIST guidelines&lt;/a&gt; on the strength of memorized secrets, both length and complexity of a password are crucial. While a minimum-length policy undoubtedly augments security, however, the same cannot be said about enforcing composition rules.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"...users respond in very predictable ways to the requirements imposed by composition rules..."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Such rules introduce three main flaws:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;An increase in rules leads to a decrease in the total number of possible passwords.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Humans exhibit predictable behaviors in attempting to meet these rules.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Constraints can sometimes make passwords more challenging to remember.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With such weaknesses, enforcing composition rules can reduce the password's inherent unpredictability, and consequently increase its vulnerability. Furthermore, it often propagates the false notion that a password is strong if and only if it lacks predictable patterns.     &lt;/p&gt;

&lt;p&gt;Consider a password like &lt;code&gt;Done_Wind_Brown1234_Pa$sword&lt;/code&gt;. Despite comprising predictable components such as "1234" and "Pas$word", it is a generally robust password due to its diverse composition, unclear pattern, and 28-character length. Therefore, binary policies that simply reject passwords for including things like sequential numbers, or for lacking numbers, can be counter productive.&lt;/p&gt;

&lt;h2&gt;
  
  
  Entropy: A Simplified Explanation
&lt;/h2&gt;

&lt;p&gt;Entropy is a direct reflection of a password's strength. To put it simply, entropy is the degree of unpredictability. It is evaluated as the total number of bits we need in order to represent all passwords from a given character pool and with a given length.&lt;/p&gt;

&lt;p&gt;The formula for calculating it is &lt;code&gt;E = log_2(N^L)&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Assuming all passwords are equally likely, there are &lt;code&gt;N^L&lt;/code&gt; possible combinations. The base-2 logarithm tells us the bits required to represent a number in binary. Hence, &lt;code&gt;log_2(N^L)&lt;/code&gt; tells us the number of bits needed to represent all possible passwords.&lt;/p&gt;

&lt;p&gt;This figure denotes the unpredictability of a randomly chosen password, because the bigger the number of bits needed to represent all possible passwords from a given pool and with a given length, the bigger the number of all possible passwords. In essence, higher entropy means a password is harder to crack because it likely requires more guesses.&lt;/p&gt;

&lt;p&gt;You have probably seen this relationship between bits of entropy and password strength in the brilliant &lt;a href="https://xkcd.com/936/"&gt;comic by XKCD&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EP7FH2LQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f1gnjq8omqoz8sn61rfo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EP7FH2LQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f1gnjq8omqoz8sn61rfo.png" alt="comic by XKCD" width="740" height="601"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Entropy Paradox
&lt;/h2&gt;

&lt;p&gt;While entropy is a robust measure, it has its limitations when applied to human-generated passwords. Why? Because it presumes all characters within a given pool are equally likely to be selected—which is far from the truth when a human is doing the selection.&lt;/p&gt;

&lt;p&gt;Consider the overly simplistic password: &lt;code&gt;1111111111111111111111&lt;/code&gt;. From a purely entropy-based perspective, it appears robust with a high value. But its predictability makes it a sitting duck for rule-based attacks, which is why many systems started incorporating composition rules.&lt;/p&gt;

&lt;p&gt;Keeping in mind the factors at play in entropy computation, and the limitation of relying blindly on it, how do we measure the strength of the password without enforcing binary composition rules?&lt;/p&gt;

&lt;p&gt;One approach is to implement a &lt;a href="https://www.uic.edu/apps/strong-password/"&gt;scoring system&lt;/a&gt; that adds and deducts points based on the elements in your password. However, the problem with such systems is that they can easily be fooled by not-so-strong passwords like &lt;code&gt;AAbbccdd112233&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making Entropy More Reliable
&lt;/h2&gt;

&lt;p&gt;Here's a question for you:&lt;/p&gt;

&lt;p&gt;What if, instead of scoring, we can re-introduce a factor of randomness to the evaluated password so that the computed entropy becomes more reliable?&lt;/p&gt;

&lt;p&gt;If we run a series of steps that gradually strip the password of predictable patterns, we end up with a sanitized version that represents the password at its core. The added randomness comes from the reduced predictability and reduced "filler slots" in the password.&lt;/p&gt;

&lt;p&gt;Going back to our example, &lt;code&gt;AAbbccdd112233&lt;/code&gt; is indeed predictable. However, it's not strictly sequential to be rejected, or with enough character repetition, because most systems can't realistically prevent you from having double letters. &lt;/p&gt;

&lt;p&gt;But why is it predictable then? Well because it's really just &lt;code&gt;Abcd123&lt;/code&gt;. That's what you see when your human eyes look at it! We can confirm its predictability by the fact that its lowercase version &lt;code&gt;aabbccdd112233&lt;/code&gt; already exists in databases of breached passwords multiple times.&lt;/p&gt;

&lt;p&gt;By identifying and eliminating patterns that act as sources of predictability, we not only increase the randomness of the sanitized password but also counteract the deceptive effect of length introduced by these patterns.&lt;/p&gt;

&lt;p&gt;If we remove the repeated characters from our example we end up with the core version: &lt;code&gt;Abcd123&lt;/code&gt;. If we now remove the sequential characters we end up with &lt;code&gt;A1&lt;/code&gt;. Factoring this version in the computation of entropy leads to a far more reliable number.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bringing It All Together: A New Verifier in Town
&lt;/h2&gt;

&lt;p&gt;I played around with this idea these past couple of weeks, and ended up creating what I believe to be a versatile library that I called &lt;a href="https://www.npmjs.com/package/pass-profiler"&gt;pass-profiler&lt;/a&gt;. It is robust enough by default to require good practices in creating passwords without enforcing any particular policy. It is also highly configurable to allow developers to define their own criteria of "predictable".&lt;/p&gt;

&lt;p&gt;The library is written in TypeScript and is compatible with both Node.js and browser environments.&lt;/p&gt;

&lt;p&gt;I believe this to be a novel approach in measuring password strength that - despite being a work-in-progress in need for extensive testing - is proving to be much harder to trick than many other strength meters available.&lt;/p&gt;

</description>
      <category>security</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Data Privacy: How Much is too Much to Share for 'Free'?</title>
      <dc:creator>Ghaleb</dc:creator>
      <pubDate>Wed, 04 Oct 2023 09:27:05 +0000</pubDate>
      <link>https://dev.to/ghamadi/online-data-how-much-is-too-much-to-share-for-free-35el</link>
      <guid>https://dev.to/ghamadi/online-data-how-much-is-too-much-to-share-for-free-35el</guid>
      <description>&lt;p&gt;There's an excellent quote that I've always been a fan of:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When something online is free, you're not the customer, you're the product.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This sentiment has always deeply resonated with me and has often deterred me from sharing information online, even on platforms that are considered private.&lt;/p&gt;

&lt;p&gt;However, views on what qualifies as sensitive data differ from person to person. I wonder, which type of data makes a free service lose its allure?&lt;/p&gt;

&lt;p&gt;From my perspective, most personal data should be treated as sensitive. If I'm considering a service that primarily handles personal information in the cloud, I'd only opt for it if it operates on a viable and transparent business model (i.e., not a free service) and ensures end-to-end encryption.&lt;/p&gt;

&lt;p&gt;Without such a model—which admittedly might trade off some features for increased security—the potential dangers associated with various data forms become magnified in the face of breaches or leaks. Your exposed financial data paints a target on your back. An online diary brimming with intimate thoughts and insights into your mental health is a recipe for disaster. Furthermore, as AI continues its upward trajectory, heightening our reservations about both sharing and privately archiving photos or videos online is long overdue.&lt;/p&gt;

&lt;p&gt;Even data we might dismiss as "trivial" can have profound consequences when leaked or pooled together. The digital landscape is rife with tales of social engineering exploits, price discrimination, identity theft, financial fraud, ransomware, and more.&lt;/p&gt;

&lt;p&gt;Yet, the "free-of-charge" aspect of many services remains alluring. Some services are sometimes just nice to have and do not justify a fee. The question to me becomes: When does &lt;em&gt;privacy&lt;/em&gt; justify that fee?&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>privacy</category>
      <category>security</category>
      <category>cloud</category>
    </item>
    <item>
      <title>The useEffect Conversations we Shouldn't be Having Anymore</title>
      <dc:creator>Ghaleb</dc:creator>
      <pubDate>Sun, 17 Sep 2023 09:00:00 +0000</pubDate>
      <link>https://dev.to/ghamadi/the-useeffect-conversations-we-shouldnt-be-having-anymore-5a3n</link>
      <guid>https://dev.to/ghamadi/the-useeffect-conversations-we-shouldnt-be-having-anymore-5a3n</guid>
      <description>&lt;p&gt;Many of the best practices and pitfalls of &lt;code&gt;useEffect&lt;/code&gt; have been discussed in depth in several great articles. However, its relationship with the component's state, and how limited that should be, is probably discussed to a lesser degree. More precisely, the exact purpose of &lt;code&gt;useEffect&lt;/code&gt; seems to allure beginners still.&lt;/p&gt;

&lt;p&gt;For instance, in a &lt;a href="https://www.reddit.com/r/reactjs/comments/15t4ql9/why_would_anyone_use_react/"&gt;post&lt;/a&gt; listing reasons &lt;em&gt;not&lt;/em&gt; to use React, a Reddit user made this argument:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;State is immutable in react. Meaning you’ll have to juggle your way around useEffect&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The way &lt;code&gt;useEffect&lt;/code&gt; is brought into this statement tells me that the person's pain with React is largely self-inflicted.&lt;/p&gt;

&lt;p&gt;Therefore, at the risk of being redundant, considering how well the React docs cover &lt;code&gt;useEffect&lt;/code&gt;, this post aims to be a comprehensive guide discussing the hook in detail—covering topics such as its fundamental purpose, how it works, and when to (and not to) use it.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Jump down to the summary 🙂&lt;/p&gt;




&lt;h2&gt;
  
  
  The Purpose of &lt;code&gt;useEffect&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;In React, &lt;code&gt;useEffect&lt;/code&gt; is a double-edged sword.&lt;/p&gt;

&lt;p&gt;It is a powerful tool in the world of functional components, but it will also nick the wielder who does not understand how functional components work, and when an effect is needed—which is rarely.&lt;/p&gt;

&lt;p&gt;Let's start with this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;useEffect&lt;/code&gt; is &lt;em&gt;not&lt;/em&gt; React's answer to reactivity.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In other words, its purpose is not to monitor some state elements through the dependency array to alter other state elements.&lt;/p&gt;

&lt;p&gt;An &lt;em&gt;effect&lt;/em&gt; is typically something you want to do after rendering takes place, and often involves interaction with the outside world. Like an event handler, it operates outside the main render flow. However, unlike an event handler, it isn't explicitly triggered; it simply runs after a component renders (more on this later).&lt;/p&gt;

&lt;p&gt;Effects can include a variety of tasks such as fetching data, subscribing to some event (notice: subscribing, not handling), manipulating the DOM directly, setting up timers, or cleaning up after certain actions.&lt;/p&gt;

&lt;p&gt;You can't do any of these things in the rendering code directly for two main reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The rendering code is responsible only for computing the values required to render.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You cannot guarantee how many times a component re-renders. Imagine adding an event listener or making an API call every time a component re-renders.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So, what is the primary purpose of &lt;code&gt;useEffect&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;It is the escape hatch we need to perform &lt;strong&gt;&lt;em&gt;a side effect that should not be part of the rendering logic and is not related to an event&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That's all it is, and that's &lt;em&gt;all&lt;/em&gt; it should be used for. Excluding some exceptional edge cases, any other form of reliance on &lt;code&gt;useEffect&lt;/code&gt; signals bad design.&lt;/p&gt;




&lt;h2&gt;
  
  
  How &lt;code&gt;useEffect&lt;/code&gt; Works
&lt;/h2&gt;

&lt;p&gt;Now that we've established what &lt;code&gt;useEffect&lt;/code&gt; is meant for, let's delve into the specifics of how it works.&lt;/p&gt;

&lt;h3&gt;
  
  
  When does an effect run?
&lt;/h3&gt;

&lt;p&gt;First, let's take a quick look at the various phases a component goes through before being displayed:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;A render is triggered&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The component is rendered and diffed with the DOM&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The changes are committed to the DOM&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These phases are always the same, and in that order, regardless of whether the component just mounted or was updated.&lt;/p&gt;

&lt;h4&gt;
  
  
  So where do effects come in?
&lt;/h4&gt;

&lt;p&gt;Effects run at the end of a commit, &lt;em&gt;after&lt;/em&gt; the screen updates.&lt;/p&gt;

&lt;p&gt;This ensures that the effect always has access to the most up-to-date state and props. It also makes sense, because effects shouldn't typically be involved in the rendering logic.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;EmptyComponent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;This line is logged second&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;This line is logged first&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With that in mind, let's update the component's phases:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;A render is triggered&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The component is rendered and diffed with the DOM&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The changes are committed to the DOM&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Effects run&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  The Dependency Array
&lt;/h3&gt;

&lt;p&gt;If you only pass the callback argument to &lt;code&gt;useEffect&lt;/code&gt;, then that effect will run after every component render.&lt;/p&gt;

&lt;p&gt;However, you can - and in most cases you should - control when an effect runs by passing a second argument to the hook, known as the dependency array. With this array, the effect will run when the component first mounts, and on any subsequent re-render where the elements in the array change.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Runs after every render&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Runs once after the initial render&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

&lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Runs after every render, provided that `count` changes&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Be careful here, though. It is easy to fall into the trap of assuming the effect runs because the dependency array changed, which is false. Without triggering a render, the effect doesn't magically run.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;counterRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// This effect will only run once, &lt;/span&gt;
  &lt;span class="c1"&gt;// no matter how many times counterRef.current is incremented&lt;/span&gt;
  &lt;span class="c1"&gt;// because updating a ref value does not trigger a render&lt;/span&gt;
  &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;counterRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;counterRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;counterRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        Increment Counter
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With that, let's update the component's phases again:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;A render is triggered&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The component is rendered and diffed with the DOM&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The changes are committed to the DOM&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Effects run (subject to dependency array change)&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  The Cleanup Callback
&lt;/h3&gt;

&lt;p&gt;Because &lt;code&gt;useEffect&lt;/code&gt; can run many times, we need a mechanism to "clean up" some code that is outside the component's control.&lt;/p&gt;

&lt;p&gt;Consider this example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;useTimeLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pageName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;timeRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Time since loading &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;pageName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;timeRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;s`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;pageName&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's assume we have this custom hook being called from various pages in our multi-route app. You load the app in &lt;code&gt;Page A&lt;/code&gt; and the logger begins working as expected. What happens when you go from &lt;code&gt;Page A&lt;/code&gt; to &lt;code&gt;Page B&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;If you guessed that you'll start getting mixed logs for both pages even though you left &lt;code&gt;Page A&lt;/code&gt;, you would be correct. Even though the component of &lt;code&gt;Page A&lt;/code&gt; unmounted, we never canceled its interval.&lt;/p&gt;

&lt;p&gt;To cancel an effect, we use the cleanup callback&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;useTimeLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pageName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;timeRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;interval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Time since loading &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;pageName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;timeRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;s`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;clearInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nx"&gt;timeRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;pageName&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;React will call your cleanup function &lt;em&gt;after&lt;/em&gt; committing the rendered changes and &lt;em&gt;before&lt;/em&gt; the effect runs next time.&lt;/p&gt;

&lt;p&gt;So, now the component's phases become:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;A render is triggered&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The component is rendered and diffed with the DOM&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The changes are committed to the DOM&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Previously registered cleanup callbacks run (subject to dependency array change)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Effects run (subject to dependency array change)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cleanup callbacks are registered&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Note that the cleanup function is also subject to the dependency array. Not all the registered cleanup functions run after a render; only those of which the dependency array changed.&lt;/p&gt;

&lt;p&gt;Also, just like all effects run when the component first mounts, all cleanup functions run when the component unmounts.&lt;/p&gt;

&lt;p&gt;To see this in action, consider this example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;effect&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cleanup&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;render&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the component first mounts, the logs show:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;render 0
effect 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the counter button is clicked:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;render 1
cleanup 0
effect 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the component is unmounted at that point, we get:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cleanup 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Effects and their cleanups should always be together
&lt;/h3&gt;

&lt;p&gt;In some rare cases, you might be tempted to have a &lt;code&gt;useEffect&lt;/code&gt; that only returns a cleanup function. Be careful if you do that because one of two things are very likely to have occurred:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;You don't have an effect&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You are cleaning up an effect that lives in another &lt;code&gt;useEffect&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In the first case, you likely don't need &lt;code&gt;useEffect&lt;/code&gt; and you should reconsider what that cleanup callback is doing.&lt;/p&gt;

&lt;p&gt;The second case is generally a bad idea, which in edge cases can lead to unexpected behavior—&lt;em&gt;especially if the dependency arrays are different&lt;/em&gt;. Remember that the cleanup callback will run &lt;em&gt;before&lt;/em&gt; the next effect. If your cleanup has different dependencies than your effect, you may get into problems.&lt;/p&gt;

&lt;p&gt;In all cases, this is bad practice. I can't picture a scenario in which one might need to do this, except when converting class components to functional components. Sometimes when converting class components, we attempt to mimic the lifecycle hooks with &lt;code&gt;useEffect&lt;/code&gt; so &lt;code&gt;componentWillUnmount&lt;/code&gt; maps to a &lt;code&gt;useEffect&lt;/code&gt; with an empty array and a cleanup callback only.&lt;/p&gt;

&lt;p&gt;I once worked on a project that had such code, and it ended up being a bad call in every single instance, which brings us to our next point.&lt;/p&gt;




&lt;h2&gt;
  
  
  What &lt;code&gt;useEffect&lt;/code&gt; is NOT meant for
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. It is NOT a lifecycle hook
&lt;/h3&gt;

&lt;p&gt;Functional components are fundamentally different from class components. A functional component is designed to fully run on every render. In contrast, in class components, the instance persists until the component unmounts, and only certain methods are called more than once depending on the component's current lifecycle stage.&lt;/p&gt;

&lt;p&gt;Accordingly, mapping class components to functional components should be done on a fundamental level as well. We should not be looking at the class's lifecycle methods and thinking about which version of &lt;code&gt;useEffect&lt;/code&gt; to use for mapping it. Nor should we necessarily map all the class's state object directly for that matter. Instead, the component as a whole should be rethought within the bounds of the functional components paradigm.&lt;/p&gt;

&lt;p&gt;Always remember: Converting components is rarely a one-to-one mapping operation.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. It is NOT part of the rendering logic
&lt;/h3&gt;

&lt;p&gt;This is an intriguingly common misuse of the hook. If you have read React code, or gone through some tutorials, you have probably seen something like this before:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;LoginForm&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setEmail&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setPassword&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isFormValid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsFormValid&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Update `isFormValid` based on `email` and `password`&lt;/span&gt;
  &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isEmailValid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isPassValid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;setIsFormValid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isEmailValid&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;isPassValid&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; 
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; 
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; 
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"password"&lt;/span&gt;
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setPassword&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; 
        &lt;span class="na"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isFormValid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        Login
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works, but it's bad practice for three main reasons:&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Readability-wise, this doesn't scale
&lt;/h4&gt;

&lt;p&gt;We are detaching the event-triggered effect from the event handler. We have no way to go directly from the event handler to the effect, without reading the entire code. This becomes a much bigger problem with more complex components.&lt;/p&gt;

&lt;p&gt;This also leads to inconsistent patterns: sometimes you apply a visual change from the event handler, and sometimes the change comes from some &lt;code&gt;useEffect&lt;/code&gt; callback.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Performance-wise, this is bad
&lt;/h4&gt;

&lt;p&gt;Recall that an effect runs &lt;em&gt;after&lt;/em&gt; the render is committed. Let's walk this through:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Our event handlers trigger a component re-render every time we type&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The changes are diffed and committed to the DOM&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The effect runs, and it updates the state&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The updated state triggers another re-render&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So this code commits to the DOM twice after a single trigger. You can imagine how 'twice per trigger' could start being an issue if, say, you had a large table with editable fields.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. We are managing more state than necessary
&lt;/h4&gt;

&lt;p&gt;As a general rule, the more state the component manages, the more complex it becomes. Accepting this pattern above leads to the bad habit of adding unnecessary state.&lt;/p&gt;

&lt;p&gt;This case does not need &lt;code&gt;useEffect&lt;/code&gt; because it is not running an effect in the first place. Once we start dedicating &lt;code&gt;useEffect&lt;/code&gt; to its intended purpose, we start thinking in a different pattern, and we end up with code that is more predictable and more performant.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;LoginForm&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setEmail&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setPassword&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// isFormValid becomes a derived value, not a state&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isEmailValid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isPassValid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isFormValid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;isEmailValid&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;isPassValid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; 
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; 
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; 
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"password"&lt;/span&gt;
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setPassword&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; 
        &lt;span class="na"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isFormValid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        Login
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, if the computation of a derived value is expensive, the solution wouldn't be the dependency array of &lt;code&gt;usEffect&lt;/code&gt;. The solution is &lt;code&gt;useMemo&lt;/code&gt;!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isFormValid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useMemo&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;someComplexValidator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;someComplexValidator&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. It is NOT an event listener
&lt;/h3&gt;

&lt;p&gt;Assume the code above wasn't validating the form, but was instead saving the form data to &lt;code&gt;localStorage&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️WARNING: This example is only to illustrate a misuse of &lt;code&gt;useEffect&lt;/code&gt;. Please don't store passwords in &lt;code&gt;localStorage&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You might argue that this is an effect because it is not part of the rendering logic, and decide to use &lt;code&gt;useEffect&lt;/code&gt; for it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;password&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The logic above is indeed a side effect. However, this effect is triggered by the &lt;code&gt;onChange&lt;/code&gt; events of the email and password input fields.&lt;/p&gt;

&lt;p&gt;While relying on &lt;code&gt;useEffect&lt;/code&gt; here does not entail adding state or rendering twice, it does detach the event-triggered-effect from the event handler. Despite resulting in a few more lines of code, it is far cleaner to keep &lt;em&gt;all&lt;/em&gt; event-handling logic in the event handler.&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;useEffect&lt;/code&gt; hook is a powerful tool in a React developer's toolkit, but it is not a Swiss army knife designed for a multitude of tasks. Nor is it a tool to group event-triggered effects of multiple elements in one place.&lt;/p&gt;

&lt;p&gt;It is mainly an escape hatch for side effects that are not triggered by events. Your component will be much more predictable and maintainable if you understand its core purpose and stick to it.&lt;/p&gt;

&lt;p&gt;As a rule of thumb, only use &lt;code&gt;useEffect&lt;/code&gt; when two conditions apply:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The logic is a genuine side effect&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The logic is not triggered by an event&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If your &lt;code&gt;useEffect&lt;/code&gt; callback does not involve a side effect and involves render-related logic, then you likely need a computed value. If the computation is expensive and you only want it reacting to a specific state change, use &lt;code&gt;useMemo&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The phases a component goes through are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;A render is triggered&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The component is rendered and diffed with the DOM&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The changes are committed to the DOM&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Previously registered cleanup callbacks run (subject to dependency array change)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Effects run (subject to dependency array change)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cleanup callbacks are registered&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Just because the hook uses a dependency array, doesn't mean it is listening for changes. An effect runs after a render is triggered, not because a dependency value changed.&lt;/p&gt;

&lt;p&gt;Finally, do &lt;em&gt;not&lt;/em&gt; treat &lt;code&gt;useEffect&lt;/code&gt; as a lifecycle hook. Convert class components by rethinking them in the functional paradigm instead of just mapping their state and lifecycle methods.&lt;/p&gt;

</description>
      <category>react</category>
      <category>beginners</category>
      <category>frontend</category>
      <category>webdev</category>
    </item>
    <item>
      <title>You Don't Need Redux: Embracing Component-Centric State Management in React</title>
      <dc:creator>Ghaleb</dc:creator>
      <pubDate>Thu, 01 Jun 2023 09:12:46 +0000</pubDate>
      <link>https://dev.to/ghamadi/embracing-component-centric-state-management-in-react-26hk</link>
      <guid>https://dev.to/ghamadi/embracing-component-centric-state-management-in-react-26hk</guid>
      <description>&lt;p&gt;It is relatively easy for an app to outgrow reliance on props for sharing state between components. Before the days of the Context API and hooks, centralized state management solutions (mainly Redux) were the go-to tools to efficiently read and update state across the app.&lt;/p&gt;

&lt;p&gt;The question now is whether such solutions remain necessary to scale an application. This post attempts to justify that the answer is "No". &lt;/p&gt;

&lt;p&gt;This is hopefully achievable by exploring the challenges that centralized state management introduces, and the way to circumvent the performance cost of the - much more flexible - Context API. &lt;/p&gt;

&lt;h2&gt;
  
  
  The Pitfalls of Centralized State Management
&lt;/h2&gt;

&lt;p&gt;Centralizing all shared state, by definition, makes all shared state global. This can lead to leaner components as they become more focused on presentation than on the data itself. It also prevents prop-drilling which we can all agree is an absolute nightmare to track or - God forbid - refactor.&lt;/p&gt;

&lt;p&gt;However, these benefits come with a tradeoff in terms of code readability. Even assuming good design i.e., keeping what should be local state local, we will end up with more global state than necessary. Generally speaking, the more global state we have, the higher the maintenance impact in two main aspects:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Code Flow
&lt;/h3&gt;

&lt;p&gt;It is far easier to follow the code when the component's state is co-located with its rendering logic. When that's not possible, it remains easier to track the state of a closely related, small subtree of components that can be thought of as a module.&lt;/p&gt;

&lt;p&gt;There is rarely, if ever, a reason for the entire application to be a single set of tightly coupled atomic parts; which means there is rarely a justifying reason to have state accessible by all atomic parts.&lt;/p&gt;

&lt;p&gt;Tracking state, and therefore clearly understanding the &lt;em&gt;why&lt;/em&gt; behind your app's behavior, is greatly improved by respecting ownership. That is, when the logical owner of a state is the one initializing it and controlling which children at the lower levels of the app's component tree can access or mutate it.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Code Complexity
&lt;/h3&gt;

&lt;p&gt;Global state inherently adds complexity because it can be altered from anywhere in the app which makes the consuming component less predictable, and harder to test. &lt;/p&gt;

&lt;p&gt;Dan Abramov, the co-creator of Redux, acknowledges that this is the main issue of using the library. &lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1241756566048694272-214" src="https://platform.twitter.com/embed/Tweet.html?id=1241756566048694272"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1241756566048694272-214');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1241756566048694272&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;First of all, I think it's interesting - to say the least - that the co-creator of Redux doesn't like it very much. &lt;/p&gt;

&lt;p&gt;More to the point, while Dan's response acknowledges that needlessly globalizing state can be detrimental, I think the original tweet was on to something. It is true that where the state is &lt;em&gt;managed&lt;/em&gt; is easy to track in Redux. However, can the same be said about knowing which components &lt;em&gt;use&lt;/em&gt; the state?&lt;/p&gt;

&lt;p&gt;Given a state, you know where the code lies by following the reducer chain. You also know what controls the state by following the actions. However, you don't readily know what the state affects—there is no easy way to know which &lt;code&gt;useSelector&lt;/code&gt; call is actually reading it. &lt;/p&gt;

&lt;p&gt;One argument here could be that this is a matter of design. We could limit the use of the central store to state that is truly global.&lt;/p&gt;

&lt;p&gt;But then it becomes questionable whether a full-featured library is actually needed to manage state that is strictly global. Except for maybe some edge cases, only a fraction of an app's total state &lt;em&gt;needs&lt;/em&gt; to be global, and such state typically doesn't change often (think user info).&lt;/p&gt;

&lt;h2&gt;
  
  
  The Complexity of Managing Server State with Centralized Solutions
&lt;/h2&gt;

&lt;p&gt;When the app involves some sort of server state (like most apps do) the central store usually ends up being used as a cache for the server data, even though that is not its purpose. Additionally, "caching" using the central store adds a great deal of complexity because server state involves more than the data; it involves the state of the request as well.  &lt;/p&gt;

&lt;p&gt;To manage server state with a centralized solution, there are generally two approaches:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Defer the fetching action to the state management solution (e.g. thunks in Redux) which would handle the loading and error states of the requests, then store the response's data in the global store.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Handle the request along with its loading and error states inside an effect, then store the response's data in the global store.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To state the obvious, the last step is common between both approaches. The problem with this step is that we now have two sources of truth: the server, and the store. This clearly, and unnecessarily, introduces the complexity of keeping them in sync.&lt;/p&gt;

&lt;h3&gt;
  
  
  Caching Solutions
&lt;/h3&gt;

&lt;p&gt;To keep the server as the single source of truth, we begin with the URL.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-699316556925243392-692" src="https://platform.twitter.com/embed/Tweet.html?id=699316556925243392"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-699316556925243392-692');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=699316556925243392&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;To elaborate on a succinct statement of wisdom, a URL generally provides two key pieces of information: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Where you are in the app&lt;/li&gt;
&lt;li&gt;Key data elements that define your state&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Dynamic data in the form of path and query parameters can take you a long way in providing your components with the state they need. You don't &lt;em&gt;need&lt;/em&gt; to store data across various stages of your app for it to work. What you need is the data's defining ID which you can grab from the URL and throw at the server. Naturally, this will have a performance impact on your app, but the important thing to note here is that it does not break functionality.&lt;/p&gt;

&lt;p&gt;As for the performance impact, while a central store &lt;em&gt;can&lt;/em&gt; be used to mitigate it, that's not a store's purpose. Dealing with that problem is where dedicated data-fetching and caching solutions like React Query and SWR come in.&lt;/p&gt;

&lt;p&gt;With features like deduping, auto re-fetching, and tracking the request's various state elements; these libraries not only eliminate the need for a global store to manage server state, but also allow for true separation of concerns that is in line with React's philosophy by allowing developers to fetch data where it is used—separating concerns by separating entities.&lt;/p&gt;

&lt;p&gt;Deduping and caching with timers like &lt;code&gt;staleTime&lt;/code&gt; and &lt;code&gt;cacheTime&lt;/code&gt; allow each component to handle its own server state without any performance impact. This plays a significant part in decoupling components—or at least decoupling subtrees of components.&lt;/p&gt;

&lt;p&gt;On the other hand, handling server state in a centralized store leads to managing more state than necessary directly in the app, and inevitably leads to tight coupling of components. Both factors significantly increase the complexity of your app, and there is little added value left in using such an approach.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Context API is not Problem Free
&lt;/h2&gt;

&lt;p&gt;Despite the arguments made so far, there is still one area in which a state-management library clearly trumps a regular context: performance.&lt;/p&gt;

&lt;p&gt;The main problem with the Context API is that when the &lt;code&gt;Provider&lt;/code&gt; re-renders due to some change in its state, &lt;em&gt;every&lt;/em&gt; &lt;code&gt;Consumer&lt;/code&gt; re-renders regardless of whether it was affected by that state or not. This is fundamentally different from how Redux state consumers behave. With Redux, only the components consuming the altered state re-render.&lt;/p&gt;

&lt;p&gt;At first glance, this might seem like a deal breaker. However, there are two important points to consider here: &lt;/p&gt;

&lt;h3&gt;
  
  
  1. This is not always an issue
&lt;/h3&gt;

&lt;p&gt;In cases where the subtree that re-renders is small, or the provider's state is not expected to change frequently (e.g. &lt;code&gt;AuthProvider&lt;/code&gt;); the performance difference becomes irrelevant. Difference in performance is only a factor when it is significant (even mildly significant); not when you are micro-optimizing.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. It is easy to achieve selective re-rendering with the Context API
&lt;/h3&gt;

&lt;p&gt;The key point to remember in the issue at hand is that the re-rendering chain begins when the state of the provider changes. What if we can have consumers subscribe to changes that are not part of React's state? In other words, what if we could achieve reactivity using the Context API without allowing the &lt;code&gt;Provider&lt;/code&gt; component to re-render?&lt;/p&gt;

&lt;p&gt;What Redux and other solutions do isn't magic. It is relatively simple to achieve similar selective reactivity using the Context API as well. Jack Harrington had an &lt;a href="https://www.youtube.com/watch?v=ZKlXqrcBx88"&gt;excellent video&lt;/a&gt; about this. And, to make a point, I actually &lt;a href="https://github.com/ghamadi/react-nimble-store/tree/main"&gt;abstracted away the logic&lt;/a&gt; of creating a smarter context where the provider doesn't blindly re-render consumers. The library is less than 100 lines of actual code (including type definitions). As I said, it's relatively simple.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making the Case for React Context
&lt;/h2&gt;

&lt;p&gt;Ultimately, the aim is to strike a balance between two extremes: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Mixing server and client state in one store and globalizing most of the app's state&lt;/li&gt;
&lt;li&gt;Prop drilling client state and having every other component make an API call even when it can easily grab a value from the parent&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I think it is possible to reach some point in the middle by adhering to these principles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Default to props until you start prop-drilling&lt;/li&gt;
&lt;li&gt;Create a context when props are not enough&lt;/li&gt;
&lt;li&gt;The context provider should be at the lowest possible level in the component tree. This is usually also the logical owner of the state&lt;/li&gt;
&lt;li&gt;The server state's parameters should in most cases be URL parameters&lt;/li&gt;
&lt;li&gt;Use a data-fetching/caching library&lt;/li&gt;
&lt;li&gt;The same principle for deciding where to place a context provider applies for deciding where to fetch the data&lt;/li&gt;
&lt;li&gt;When the state is expected to change frequently, or is needed globally, use a &lt;a href="https://github.com/ghamadi/react-nimble-store/tree/main"&gt;smarter context&lt;/a&gt; (or use that everywhere)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Our focus should always be on building robust, maintainable applications, and our weapon of choice should be dictated by that. The heaviest sword is not always the right one, and while centralized state management solutions such as Redux were, and continue to be, powerful tools for building complex applications, they are not necessary for the majority of the cases.&lt;/p&gt;

&lt;p&gt;The rise of React's Context API, hooks, and data-fetching libraries like React Query present developers with the ability to manage state in a more component-centric, efficient, and flexible manner. These tools facilitate the co-location of state and logic, improve code readability, and simplify state flow. Relying on centralized stores trades off these features and the benefit is only clear in a small subset of applications where state needs to be globalized.&lt;/p&gt;

</description>
      <category>react</category>
      <category>webdev</category>
      <category>development</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Building a Portfolio: A Project Idea</title>
      <dc:creator>Ghaleb</dc:creator>
      <pubDate>Sun, 30 May 2021 20:19:36 +0000</pubDate>
      <link>https://dev.to/ghamadi/building-a-portfolio-a-project-idea-48bh</link>
      <guid>https://dev.to/ghamadi/building-a-portfolio-a-project-idea-48bh</guid>
      <description>&lt;p&gt;In the first part of this series, I introduced the general factors that generally make up a good project. Today, I will be suggesting a project idea, why it works, and some recommended features.&lt;/p&gt;

&lt;p&gt;I will also share a few resources that can be useful for full-stack developers when creating this project. The idea itself is not limited to web development, but I will be discussing it from the perspective of full-stack web developers.&lt;/p&gt;




&lt;h1&gt;
  
  
  The Project: A Password Manager
&lt;/h1&gt;

&lt;p&gt;Password managers are not a new idea by any means, and managing passwords is not an &lt;em&gt;unsolved problem&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;There is a large number of solutions out there, so you will not be in lack of resources for inspiration. The large number of solutions, however, should not discourage you from implementing one yourself.&lt;/p&gt;

&lt;p&gt;I believe a password manager is comprehensive enough to be a good addition to most, if not all, portfolios. It is also complex enough to help you show your skills.&lt;/p&gt;

&lt;p&gt;Security is a very important component of any full-stack project, and password managers employ a suite of security concepts. Presenting a password manager not only equates presenting essential skills for full-stack development, but also your familiarity with security concepts. A password manager is also a useful project.&lt;/p&gt;

&lt;p&gt;It is one thing when you build an unpublished, dummy project. It is another thing entirely when that project is in active use. A published project conveys confidence in the implementation, and makes your sales pitch more convincing.&lt;/p&gt;

&lt;p&gt;A password manager is not limited to a small audience; it is useful to almost everyone. As such, finding a decent number of users in your circle of friends and family is not hard.&lt;/p&gt;

&lt;p&gt;I do have one warning here: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you are not at all familiar with concepts of security, or you do not intend to maximize security, then limit the users of the project to yourself, and avoid sensitive data (or keep it local).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Another great aspect of this project idea, is that it inherently involves user management and non-trivial CRUD operations. A couple of unrelated tables (or document collections if you wish to use something like Firebase) will not be enough for a decent implementation. &lt;/p&gt;

&lt;p&gt;So, even if you do not care about maximizing security, your project will check most boxes in the list of skills needed for your full-stack position.&lt;/p&gt;




&lt;h1&gt;
  
  
  Why it Works: Key Factors
&lt;/h1&gt;

&lt;h3&gt;
  
  
  1. Problem statement
&lt;/h3&gt;

&lt;p&gt;The importance of a password manager is well documented and is only expected to increase. As a matter of fact, password managers have become necessary if a user wishes to claim security. &lt;/p&gt;

&lt;p&gt;So, problem statement: ✔&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Data persistence
&lt;/h3&gt;

&lt;p&gt;Another obviously present component in this project. More importantly, the data model required for a proper password manager is not overly simple. &lt;/p&gt;

&lt;p&gt;At the very least, a basic - but useful - password manager needs to handle users, roles, and multiple types of secure items (not just accounts' passwords).&lt;/p&gt;

&lt;p&gt;So, clearly, data persistence: ✔&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Decent scope
&lt;/h3&gt;

&lt;p&gt;The scope of your application primarily depends on how much work you intend to invest in it. To justify this project idea however, we should discuss the minimal functionality required.&lt;/p&gt;

&lt;p&gt;The core features would be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authentication &amp;amp; authorization&lt;/li&gt;
&lt;li&gt;Client-side encryption &amp;amp; decryption of data&lt;/li&gt;
&lt;li&gt;A secure, random password generator&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Other good-to-have features could be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Custom fields for secure items (allow user to add, remove, and rename fields of whatever secure items they wish to store)&lt;/li&gt;
&lt;li&gt;Editable templates of secure items&lt;/li&gt;
&lt;li&gt;Sharing encrypted data among users (public key encryption)&lt;/li&gt;
&lt;li&gt;Authenticating stored items (use case for HMAC)&lt;/li&gt;
&lt;li&gt;Master password reset (not a trivial problem to solve since the forgotten master password is needed to decrypt stored items)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All the features above are important. You can either create a basic application with the core features, or expand it with the good-to-have features. Either way, you are still no where near nice-to-have features, and the scope of your application is already non-trivial.&lt;/p&gt;

&lt;p&gt;Decent scope: ✔&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Clean architecture
&lt;/h3&gt;

&lt;p&gt;Mostly because of the 'decent scope', you will increasingly suffer as you work on your project if you are not applying good coding practices. &lt;/p&gt;

&lt;p&gt;In other words, a project like this one almost forces you to carefully consider your architecture properly before implementing.&lt;/p&gt;

&lt;p&gt;This will be your responsibility as a developer. It cannot really be expanded upon here without explicitly discussing an implementation, which is beyond the scope of this article.&lt;/p&gt;

&lt;p&gt;Note that it might be a good idea to document your architecture if you intend to showcase your project later on.&lt;/p&gt;

&lt;p&gt;Clean architecture: ✔&lt;/p&gt;




&lt;h1&gt;
  
  
  Why it Works: Bonus Points
&lt;/h1&gt;

&lt;h3&gt;
  
  
  1. Encryption vs Hashing
&lt;/h3&gt;

&lt;p&gt;Remember, this is a project that emphasizes security. You do not have the option of storing passwords in plaintext and claiming that this is a dummy project and you wanted to focus on core functionality :) &lt;/p&gt;

&lt;p&gt;You will have to hash users' authentication passwords and encrypt their secure items. That means you will need to understand the exact differences between the two concepts, as well as the differences between the different algorithms within each realm. You will also need to understand best use cases for different algorithms to justify your choices.&lt;/p&gt;

&lt;p&gt;In short, this project helps you demonstrate good working knowledge in different security concepts.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. API consumption (optional)
&lt;/h3&gt;

&lt;p&gt;This was listed as an optional key component of a good project in my previous post. You will probably not need to consume an API for the core functionality of this app, but you can get creative with nice-to-have features.&lt;/p&gt;

&lt;p&gt;This is entirely optional, but you are expected to deal with APIs as an engineer, and as such, there is no harm in demonstrating comfort in using them.&lt;/p&gt;




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

&lt;p&gt;A password manager involves all the key components discussed to make a project fit for a full-stack developer's portfolio. &lt;/p&gt;

&lt;p&gt;More importantly, however, it also forces you to learn security concepts. These concepts are extremely relevant but often ignored or forgotten in projects, because they are not required for the app to function. &lt;/p&gt;




&lt;h1&gt;
  
  
  Resources
&lt;/h1&gt;

&lt;p&gt;Here's a list of resources that may be useful to building this web-based password manager:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.youtube.com/watch?v=w68BBPDAWr8"&gt;How Password Managers Work - Computerphile&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;I cannot recommend this video enough&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://cryptojs.gitbook.io/docs/"&gt;CryptoJS&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;A JavaScript crypto library &lt;/li&gt;
&lt;li&gt;Includes hashing and encryption algorithms&lt;/li&gt;
&lt;li&gt;Lacks asymmetric encryption&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/dchest/tweetnacl-js/blob/master/README.md#documentation"&gt;TweetNaCl.js&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;A JavaScript crypto library focused on encryption&lt;/li&gt;
&lt;li&gt;Includes asymmetric encryption but lacks HMAC &amp;amp; PBKDF2&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/davidbau/seedrandom"&gt;seedrandom&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;Seeded random number generator for JavaScript&lt;/li&gt;
&lt;li&gt;Might prove useful for a secure password generator&lt;/li&gt;
&lt;/ul&gt;


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

</description>
      <category>portfolio</category>
      <category>career</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Building a Portfolio: What to Look for in a Project </title>
      <dc:creator>Ghaleb</dc:creator>
      <pubDate>Mon, 24 May 2021 15:49:28 +0000</pubDate>
      <link>https://dev.to/ghamadi/building-a-portfolio-what-to-look-for-in-a-project-2kln</link>
      <guid>https://dev.to/ghamadi/building-a-portfolio-what-to-look-for-in-a-project-2kln</guid>
      <description>&lt;p&gt;This will be at two-part series in which I discuss my take on how &lt;br&gt;
to approach building a portfolio for new developers, and then suggest a project idea. &lt;/p&gt;

&lt;p&gt;The discussion mostly concerns full-stack development. Portfolios differ drastically across the different specializations of software engineering, so for this discussion to be of any use, we focus on one sector.&lt;/p&gt;




&lt;h1&gt;
  
  
  TL;DR
&lt;/h1&gt;

&lt;p&gt;Skip down to the Summary :) &lt;/p&gt;




&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;The importance of your portfolio varies from individual to another depending on several factors. However, it is accepted wisdom that if you plan to enter the software industry, you should have some number of projects built, even if only to showcase your knowledge.&lt;/p&gt;

&lt;p&gt;For career switchers, this is absolutely a must. So, being one myself, I spent a considerable amount of time researching the topic and looking for ideas to build projects.&lt;/p&gt;




&lt;h1&gt;
  
  
  The Main Takeaway
&lt;/h1&gt;

&lt;p&gt;If I can state one conclusion from all of the different blog posts and videos I went through on the topic, it would be this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The idea itself doesn't really matter. The execution, and the motivation behind, it absolutely does.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;By execution I obviously mean the implementation of the project. By motivation, I mean the reasons that made you believe this is a good project to showcase your ability as a full-stack candidate.&lt;/p&gt;

&lt;p&gt;This is not to say that simply listing project ideas is a bad approach. What I am saying is that developers trying to build a portfolio should understand what makes up a good project, because there might be a good idea lurking around in their own environment—one which cannot be found in lists of common topics. &lt;/p&gt;




&lt;h1&gt;
  
  
  What to Consider in a Project
&lt;/h1&gt;

&lt;p&gt;Now that we have established that the topic itself is not necessarily the property that gives the project its value, we should try to point out the ones that do.&lt;/p&gt;

&lt;p&gt;There a few components that you should look to have in your project when selecting a topic.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. A problem statement
&lt;/h3&gt;

&lt;p&gt;You want your project to show that you have made some effort to find a real-world problem and tried to solve it. &lt;/p&gt;

&lt;blockquote&gt;
&lt;h3&gt;
  
  
  Side note:
&lt;/h3&gt;

&lt;p&gt;A todo list is not a good candidate because it lacks creativity. You haven't looked hard enough if all you have found is an idea for a simple todo list.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Be careful here, though. This isn't a PhD thesis. You probably won't be able to find an unsolved problem, so don't spend your days looking instead of coding. Your goal is not to find &lt;em&gt;the perfect problem&lt;/em&gt;, but to find something you can justify the time spent solving.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Data persistence
&lt;/h3&gt;

&lt;p&gt;Unless your goal is to showcase ninja CSS skills, static pages won't cut it. The same goes for simple calculators. Just don't showcase a calculator. Please. &lt;/p&gt;

&lt;blockquote&gt;
&lt;h3&gt;
  
  
  Side note:
&lt;/h3&gt;

&lt;p&gt;If you do want to showcase ninja CSS skills, then by all means create such a project. Just don't make it your only one.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A full-stack engineer deals with data, and your project should too. You need to show a project that efficiently deals with CRUD operations and not-so-trivial queries.&lt;/p&gt;

&lt;p&gt;Now, for the database used for said persistence, perhaps relational databases are not a must—with the popularity of the MEAN &amp;amp; MERN stacks and all. But in my opinion, the better candidate is the one that can justify the tools of choice. If you are not going to use a relational database, have reasons to back your decision.&lt;/p&gt;

&lt;p&gt;Regardless of the database system of choice, your database should be well designed, and your data manipulation should be efficient.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Decent scope
&lt;/h3&gt;

&lt;p&gt;This more concerned with your implementation than the topic. The problem statement does not need to be huge, but your implementation should not be limited.&lt;/p&gt;

&lt;p&gt;You should aim to mimic an actual product. Do not cut corners with features complementary to the core feature solving the problem. &lt;/p&gt;

&lt;p&gt;A web app without authentication and authorization, for example, is usually incomplete. If your app processes large amount of data, you should consider having import/export features and not just displaying data on your UI.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Clean architecture
&lt;/h3&gt;

&lt;p&gt;Again, a property concerned with your implementation. &lt;/p&gt;

&lt;p&gt;You need to have properly applied good software engineering practices and good practices of the tech stack you chose.&lt;/p&gt;

&lt;p&gt;Encapsulation and separation of concerns are the key factors here.&lt;/p&gt;

&lt;p&gt;You do not want an architecture with global variables everywhere being affected from multiple places in your code. You also do not want your data-handling logic jumbled up with your data-rendering logic.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Some form of an API consumption
&lt;/h3&gt;

&lt;p&gt;This may not be a must have, but I think it's worth considering. &lt;/p&gt;

&lt;p&gt;If your backend is not an API itself, it may be a good idea to pick a project that requires communicating with a third party API in your project; if only for the sake of demonstrating your skills and familiarity with the concept of asynchronous data fetching and (de)serialization of objects. &lt;/p&gt;




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

&lt;p&gt;In this article, I tried to articulate the key components that make up a good project based on my own research on the topic trying to build the resume that got me my first job. The five components listed may not be the only, or the most important, ones to look for in a full-stack app, but they are what I stood out to me.&lt;/p&gt;

&lt;p&gt;These are also the components I included in my own project before applying to the company that offered me my first job as a junior full-stack developer.&lt;/p&gt;

&lt;p&gt;In the next article, I will be suggesting an idea for a project that I have not come across often, and I will be detailing why I think it is a good choice when building your portfolio.&lt;/p&gt;

&lt;p&gt;Till then, please use the comments section to share your thoughts on the matter.&lt;/p&gt;




&lt;h1&gt;
  
  
  Summary
&lt;/h1&gt;

&lt;p&gt;When looking for projects to build, you need a project that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Has a problem statement:&lt;br&gt;
That is, the project solves a problem you can articulate to your audience.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Requires data persistence:&lt;br&gt;
If the topic does not require a backend with a well-designed database, it is not a good fit for a full-stack application&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A scope beyond the feature that solves the problem:&lt;br&gt;
You need to show that you understand typical business requirements, and can develop a program with complementary features coherently implemented within the scope of your project.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Clean architecture:&lt;br&gt;
Your project should demonstrate your grasp of the principle of "Separation of Concerns". You must demonstrate that you can develop with maintainability in mind.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Consumes some API:&lt;br&gt;
A preferred feature that will show your comfort with dealing with APIs and asynchronous data fetching.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>career</category>
      <category>codenewbie</category>
      <category>portfolio</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Vue or React?</title>
      <dc:creator>Ghaleb</dc:creator>
      <pubDate>Wed, 06 Jan 2021 12:55:05 +0000</pubDate>
      <link>https://dev.to/ghamadi/vue-or-react-iih</link>
      <guid>https://dev.to/ghamadi/vue-or-react-iih</guid>
      <description>&lt;p&gt;A couple of months ago, I chose Vue to be my point of entry to the frameworks realm in web development. I also decided to go in depth-first. So, I practiced barebones Vue, then used Vuetify, then - after getting sick of all the props and emits - I learned Vuex, and now I am playing around with Nuxt. In all this, I have not even glanced at the documentation of React.&lt;/p&gt;

&lt;p&gt;What I know about React, I know from occasional blog posts. A common claim I came upon was that Vue is simpler to learn than React. And that does not seem to come with a penalty in terms of performance or robustness. As I understand, from reading and not from experience, both frameworks are equally useful for projects of different scales.&lt;/p&gt;

&lt;p&gt;At least from my experience, as I work on my first meaningful web project, I find myself constantly impressed by how simple the development process is. Especially, when component libraries like Vuetify are utilized.&lt;/p&gt;

&lt;p&gt;Assuming my understanding is correct (and feel free to enlighten me if it isn't) I have two questions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;With Vue.js readily available, is there any reason to learn React—other than the fact that React came first and therefore has the bigger market share?&lt;/li&gt;
&lt;li&gt;If no such reason exists, do you expect Vue to take over in the future? In other words, any reason for a startup project today not to be developed in Vue instead of React?&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>discuss</category>
      <category>webdev</category>
      <category>vue</category>
      <category>react</category>
    </item>
    <item>
      <title>BootstrapVue or Vuetify for a Nuxt.js Project?</title>
      <dc:creator>Ghaleb</dc:creator>
      <pubDate>Wed, 25 Nov 2020 16:00:16 +0000</pubDate>
      <link>https://dev.to/ghamadi/bootstrapvue-or-vuetify-for-a-nuxt-js-project-48hp</link>
      <guid>https://dev.to/ghamadi/bootstrapvue-or-vuetify-for-a-nuxt-js-project-48hp</guid>
      <description>&lt;p&gt;I have been reading on this topic for a couple of days now. I want to pick a UI library for my project and I am mostly torn between these two options. &lt;/p&gt;

&lt;p&gt;Looking at the documentation of both tools, I feel that Vuetify offers a bigger variety of components. Also, Vuetify's data-table component is a clear winner compared to that of BootstrapVue. &lt;/p&gt;

&lt;p&gt;However, even a quick search is enough to show that Vuetify is by no means a clear winner; many seem to prefer BootstrapVue. &lt;/p&gt;

&lt;p&gt;Disregarding any bias against material design (because I don't have any) which would you pick? And why?&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Frameworks are Powerful and Awesome and Frightening</title>
      <dc:creator>Ghaleb</dc:creator>
      <pubDate>Thu, 29 Oct 2020 14:30:11 +0000</pubDate>
      <link>https://dev.to/ghamadi/frameworks-are-powerful-and-awesome-and-frightening-19i</link>
      <guid>https://dev.to/ghamadi/frameworks-are-powerful-and-awesome-and-frightening-19i</guid>
      <description>&lt;p&gt;I am new to all this. I haven't worked in the industry yet, and I am only now building my first project for my final year at college. I played with Flutter a bit before and, more recently, with VueJS a little bit more.&lt;/p&gt;

&lt;p&gt;Frameworks, for me, seem to be a double-edged sword. On one end, they make more projects feasible to individual developers and small teams. Projects are the best way to learn, and good projects enrich the industry, so that's cool. On the other end, they seriously lower the barriers to entry and make it harder to distinguish experience by looking at the end result alone. The code will always be revealing, of course, but the code is rarely looked at.&lt;/p&gt;

&lt;p&gt;For my final-year project I am using Firebase with Quasar. This is where the fear kicked in. The combination of tools I am using made things easy; maybe even &lt;em&gt;too&lt;/em&gt; easy. &lt;/p&gt;

&lt;p&gt;Initially, I planned out long durations for small tasks to account for my lack of experience. However, once the work began, the time in which I learned the concepts and finished my authentication form with the accompanying services, surprised me. I thought I would need two weeks just for tutorials, let alone having something functional. I needed three days for both.&lt;/p&gt;

&lt;p&gt;The Firebase SDK and Firestore rules did all the backend heavy-lifting, and Quasar made me laugh at myself as I looked at the elegant form that would have maybe cost me a month to build without those out-of-the-box components.&lt;/p&gt;

&lt;p&gt;So the natural question that followed was this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How afraid should we - the new kids on the block - be from competition in such a hot industry that keeps lowering the barriers to entry? What is the most efficient approach for a noob web developer to stand out?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I would love to hear how my fears are unfounded and how my question is invalid. This may be one of the rare occasions where one wishes for disapproving opinions. &lt;/p&gt;

&lt;p&gt;So, whether you agree, have tips on how to compete, or you completely disagree; please, do share.&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>beginners</category>
      <category>career</category>
      <category>webdev</category>
    </item>
    <item>
      <title>I am Disconnecting</title>
      <dc:creator>Ghaleb</dc:creator>
      <pubDate>Mon, 12 Oct 2020 09:05:54 +0000</pubDate>
      <link>https://dev.to/ghamadi/i-am-disconnecting-10l7</link>
      <guid>https://dev.to/ghamadi/i-am-disconnecting-10l7</guid>
      <description>&lt;h1&gt;
  
  
  Context
&lt;/h1&gt;

&lt;p&gt;I have a problem with Facebook. I find myself, more times than not, habitually accessing it as soon as I open my browser or unlock my phone. &lt;/p&gt;

&lt;p&gt;I don't think I have a &lt;em&gt;surfing&lt;/em&gt; problem in general. I don't check twitter often, despite having an account. I don't get hooked to a never-ending trail of YouTube videos even though I have it on all the time to listen to my music playlists there. No, what I have is a &lt;em&gt;Facebook&lt;/em&gt; problem (and maybe a cell-phone problem).&lt;/p&gt;

&lt;p&gt;I tried tackling this issue before and I failed. &lt;/p&gt;

&lt;p&gt;The main obstacle is that I realize Facebook's danger, but I also find benefit in it, so I do not want the solution that entails deleting my account. &lt;/p&gt;

&lt;p&gt;When used with a small network of actual friends and family (or even actual acquaintances) Facebook indeed enables a rewarding experience of shared memories.&lt;/p&gt;

&lt;p&gt;Despite the benefits, however, this Facebook problem must be solved, so I am starting an experiment to be rid of it without being rid of my account. I will allow this experiment to run for a year. If it fails, I am committing right now to deleting my account permanently.&lt;/p&gt;

&lt;h1&gt;
  
  
  Dissecting the Problem
&lt;/h1&gt;

&lt;p&gt;Perhaps the reason I failed the first time I tried is that I did not accurately identify the problem. After some thought, I think I can boil it down to three issues:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The Rabbit-Hole syndrome&lt;/li&gt;
&lt;li&gt;The Last-Word syndrome&lt;/li&gt;
&lt;li&gt;The Bell syndrome&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now let's clearly define each problem so that we can clearly identify a solution.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The Rabbit-Hole Syndrome
&lt;/h3&gt;

&lt;p&gt;The reason I mechanically check Facebook every time I have some device that can access it is not that I want to check on my friend invites, or the most recent comments on my latest, popular post. I do not share often on Facebook and I do not have a vast network of friends.&lt;/p&gt;

&lt;p&gt;The magnet that hooks me is the home-feed.&lt;/p&gt;

&lt;p&gt;I cannot remember a time when I opened Facebook and did not scroll down the home-feed. Or a time when I did not finally stop to view a post and scrolled down to read the comments.&lt;/p&gt;

&lt;p&gt;Sometimes I scroll down because I am interested in what I see, other times it is because I am not. It's like I need a fix so I keep scrolling until I find a post to check.&lt;/p&gt;

&lt;p&gt;It is incredibly rare for me to read something on Facebook that is useful in expanding my intellect, but it is not rare for me to read something on Facebook.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. The Last-Word Syndrome
&lt;/h3&gt;

&lt;p&gt;Sometimes, when I read posts or comments, I have this utter discontent that burns in me from what I deem to be absolutely ridiculous. Most times I cannot  resist responding. I know – deep down I always know – that there is absolutely no gain in responding to comments, but I just do it.&lt;/p&gt;

&lt;p&gt;I almost always end up not sending the response, because I know there is no benefit, but I almost always waste time typing the full response. I articulate all the reasons why something is stupid, and then I delete them.&lt;/p&gt;

&lt;p&gt;There are occasions in which I do respond and then dwell into controversies that heat up and lead to me regretting the whole situation and deleting my comments.&lt;/p&gt;

&lt;p&gt;I think I'm easier to talk to face-to-face; I piss off people much less than I do behind a keyboard.  Words come out better when I speak them than when I type them, I think. Or maybe they don't, I don't know. 😅&lt;/p&gt;

&lt;h3&gt;
  
  
  3. The Bell Syndrome
&lt;/h3&gt;

&lt;p&gt;When I am not spontaneously opening Facebook for no good reason, you will find me opening Facebook in response to a notification. I cannot – I literally cannot – ignore the notification sound on my phone (for any app in general) or the red bell icon on my Facebook page.&lt;/p&gt;

&lt;p&gt;The notification sound is solvable by silencing the phone, which is often feasible. But how do you counter the burning urge to click/tap the notification bell, when you constantly - and mechanically - open Facebook?&lt;/p&gt;

&lt;p&gt;Another problem is that I like my posts to get reactions, so I keep checking if they do. Ironically enough, this worsens my habitual access in a positive feedback loop fashion. I hate that about myself. I do not normally find my self-worth in people's opinions, but for some reason I detest seeing my posts ignored. It's as if my personality is different on the social network.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Plan
&lt;/h1&gt;

&lt;p&gt;I have devised five phases to overcome the problems above. I call them phases because I like the word, but they are not necessarily in separate timespans. I begin today—October 12, 2020.&lt;/p&gt;

&lt;h3&gt;
  
  
  Phase 1: Disconnect
&lt;/h3&gt;

&lt;p&gt;Like with every addiction, the first phase of rehab is cutting out the drug from one's life until the temptation fades. Consequently, the first step is to deactivate Facebook. That, however, will not be enough.&lt;/p&gt;

&lt;p&gt;Disconnecting is the best way to tackle my Rabbit-Hole and Bell syndromes, which are not strictly related to Facebook. It just happens that Facebook attracts me more than other networks, but if I am ever to use Facebook in a healthy fashion, I need to tackle the root of the problem.&lt;/p&gt;

&lt;p&gt;It is not enough to deactivate Facebook and mute other notifications, I will need to filter out all the electronic non-essentials and control the essentials.&lt;/p&gt;

&lt;p&gt;In essence, I need to practice living productively without relying on notifications. In other words, practicing a life where I am not constantly reacting to triggers. &lt;/p&gt;

&lt;p&gt;Here's what's going to happen:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;I will exit all non-essential chat groups. That leaves me with only class-related chat groups which I will mute. These groups are only useful to ask questions, not to read people's chats.&lt;/li&gt;
&lt;li&gt;I will unsubscribe from all news and email feeds. I will pick two programming-related blogs and one or two newspapers to read periodically. No more responding to feed notifications or scrolling through random posts.&lt;/li&gt;
&lt;li&gt;I will remove the email clients on both my phone and computer and set an hour (or two half-hours) every day to check my personal, work, and school email accounts through their web clients. No more bells driving my actions.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Phase 2: Read (a lot)
&lt;/h3&gt;

&lt;p&gt;Starting October 12, I will dedicate gradually-increasing time every day to two reading sessions from two different books, with one being fiction and the other non-fiction. &lt;/p&gt;

&lt;p&gt;This will help create a habit of reading, and the fiction part will help turn reading from a chore to a delight. I always enjoy a good story and I'm actually quite easy to please in that aspect.&lt;/p&gt;

&lt;p&gt;Reading will also include articles. Newspaper articles and programming articles but, as explained in phase 1, it cannot be done in reaction to any notification or by scrolling through random feed. It needs to be from predefined sources that are visited at predefined hours.&lt;/p&gt;

&lt;h3&gt;
  
  
  Phase 3: Blog (with or without an audience)
&lt;/h3&gt;

&lt;p&gt;I am a post-30 Computer Science student. When I hopefully graduate next June, I will have earned two undergrad degrees and taken my first step towards switching careers.&lt;/p&gt;

&lt;p&gt;Being post 30 (aka late to the game), a successful programming career will require an online presence with a portfolio and a blog. This makes &lt;em&gt;now&lt;/em&gt; the best time to start blogging. Blogging will endow me with all its innate benefits and, importantly, provide an alternative to sharing on social media. This will allow me in the future to keep Facebook strictly for moments with family and friends.&lt;/p&gt;

&lt;p&gt;This is a tough one, though, because I still don't know much about writing and I have no blogging topic in mind. If progress stalls in this phase I will attempt journaling as a preliminary step.&lt;/p&gt;

&lt;h3&gt;
  
  
  Phase 4: Indulge in offline activities
&lt;/h3&gt;

&lt;p&gt;I am not an outdoor person. But I am a parent, and kids need outdoor time. So I will make use of the deliberate approach of this experiment to deliberately spend more outdoor, disconnected time with my family.&lt;/p&gt;

&lt;p&gt;Being a programming enthusiast, I will also include creating pet projects that I do for fun or profit. Coding should not be a practice disturbed by frequent internet surfing. It should be done with a "Deep Work" mentality. Considering that I cannot code without googling (or StackOverflow-ing), I need to practice being disconnected from the distracting part of the internet, not necessarily the internet in general. So maybe "offline" is not the best term here, but oh well.&lt;/p&gt;

&lt;p&gt;This year should be a good point to start practicing fully-focused and prolonged coding sessions. Perhaps the first pet project could be building a personal webpage.&lt;/p&gt;

&lt;h3&gt;
  
  
  Phase 5: Reconnect (carefully)
&lt;/h3&gt;

&lt;p&gt;By the end of the first four phases, I will have developed:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A resistance to surfing and an appreciation for dedicated reading time.&lt;/li&gt;
&lt;li&gt;Some experience in writing and blogging.&lt;/li&gt;
&lt;li&gt;A portfolio of small (or big) projects.&lt;/li&gt;
&lt;li&gt;Better time management skills.&lt;/li&gt;
&lt;li&gt;Higher emotional intelligence. I seriously need to stop being easily provoked into commenting.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At this point, if things go according to plan, I will have two choices: either reconnect with Facebook and unfollow everything unnecessary there, or ditch Facebook.&lt;/p&gt;

&lt;p&gt;Even if I reconnect, though, I will probably not install the app. You see, apps attract taps (no pun or rhyme intended, I swear) and I will never outsmart Facebook's engineers. The whole point of this experiment is to use social media consciously, not in a reactive fashion; so uninstalling the app is most probably permanent for me.&lt;/p&gt;

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

&lt;p&gt;So why am I sharing this publicly?&lt;/p&gt;

&lt;p&gt;Well, for one, because I do not want to post about it on Facebook 😅. &lt;/p&gt;

&lt;p&gt;On a more serious note, I want to get the feel of writing a blog post and, most importantly, I want to hold myself accountable. &lt;/p&gt;

&lt;p&gt;This may not be a Facebook post, but if you are reading this, then you're either a dev.to user or I have shared the link with you directly. No one wants to fail publicly, so I decided to commit publicly.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
