<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Diona Rodrigues</title>
    <description>The latest articles on Forem by Diona Rodrigues (@dionarodrigues).</description>
    <link>https://forem.com/dionarodrigues</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%2F393945%2F0a921add-d1a4-40e2-8e38-a8410465f3ef.jpg</url>
      <title>Forem: Diona Rodrigues</title>
      <link>https://forem.com/dionarodrigues</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/dionarodrigues"/>
    <language>en</language>
    <item>
      <title>Why Clean Code Matters: Lessons from Uncle Bob</title>
      <dc:creator>Diona Rodrigues</dc:creator>
      <pubDate>Mon, 20 Oct 2025 16:48:41 +0000</pubDate>
      <link>https://forem.com/dionarodrigues/why-clean-code-matters-lessons-from-uncle-bob-137l</link>
      <guid>https://forem.com/dionarodrigues/why-clean-code-matters-lessons-from-uncle-bob-137l</guid>
      <description>&lt;p&gt;&lt;strong&gt;Software is everywhere. Almost every part of our lives — from banking to maps to music — depends on it. And when software fails, it can cost money, waste time, or even cause real harm. As developers, that means we carry a great responsibility — the way we write code truly matters.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Uncle Bob (Robert C. Martin), a renowned software engineer, instructor, and author, reminds us that clean code is more than just style — it’s about communication. Code is read far more often than it’s written, so clarity, consistency, and simplicity are essential.&lt;/p&gt;

&lt;p&gt;In this article, inspired by &lt;a href="https://www.youtube.com/watch?v=7EmboKQH8lM&amp;amp;list=PLmmYSbUCWJ4x1GO839azG_BBw8rkh-zOj" rel="noopener noreferrer"&gt;Uncle Bob’s Clean Code lessons on YouTube&lt;/a&gt; and &lt;a href="https://github.com/ryanmcdermott/clean-code-javascript" rel="noopener noreferrer"&gt;Ryan McDermott’s JavaScript adaptation (clean-code-javascript)&lt;/a&gt;, I created a quick and practical guide, blending my notes on these timeless principles to help improve your code.&lt;/p&gt;

&lt;h1&gt;
  
  
  Clean Code Principles for JavaScript
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Naming (for functions and variables)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Names are the first level of communication in your code. They should clearly describe what a variable or function represents or does.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use meaningful, descriptive names that reveal intent.&lt;/li&gt;
&lt;li&gt;A variable name should be proportional to its scope — short names for short scopes (like loops), longer names for broader contexts.&lt;/li&gt;
&lt;li&gt;For functions, use the opposite logic: if a function is called often, keep its name short; if it’s specific or used less frequently, make it more descriptive.&lt;/li&gt;
&lt;li&gt;Stick to a consistent vocabulary across the codebase — avoid mixing terms like “user”, “client”, and “customer” if they refer to the same entity.&lt;/li&gt;
&lt;li&gt;Good formatting is crucial and should be applied consistently throughout the code.&lt;/li&gt;
&lt;li&gt;Always strive to remove dead or duplicated code to keep your codebase clean.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// BAD&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;currentDateFormattedBasedOnLocale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toLocaleDateString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;l&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;d_ir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;currentDateFormattedBasedOnLocale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en-IE&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;dtUs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;currentDateFormattedBasedOnLocale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en-US&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// GOOD&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;formatCurrentDate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toLocaleDateString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;locale&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;irishDate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;formatCurrentDate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en-IE&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;usDate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;formatCurrentDate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en-US&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Functions
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Functions are the verbs of your code — they represent actions. Clean, simple, and well-defined functions make your code easy to understand and maintain.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Function names should be verbs, because functions do things.&lt;/li&gt;
&lt;li&gt;Functions should be small and simple enough to understand quickly. If they grow too complex, extract smaller helper functions.&lt;/li&gt;
&lt;li&gt;Avoid using more than three arguments. If needed, use an object to group related parameters and destructuring syntax (a very common pattern in React).&lt;/li&gt;
&lt;li&gt;Avoid passing boolean arguments; they often mean the function does more than one thing.&lt;/li&gt;
&lt;li&gt;Functions should not cause side effects — they shouldn’t modify variables or state outside their own scope. Pure functions make behavior predictable and easier to test.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// BAD&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;u&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;notify&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;notify&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;sendNotification&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;u&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nf"&gt;logChanges&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;u&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;calculateSomething&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;u&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;saveToDatabase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;u&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// - Function name is vague&lt;/span&gt;
&lt;span class="c1"&gt;// - Too many responsibilities&lt;/span&gt;
&lt;span class="c1"&gt;// - Boolean argument alters behavior&lt;/span&gt;
&lt;span class="c1"&gt;// - Modifies external state (side effects)&lt;/span&gt;
&lt;span class="c1"&gt;// - Too many arguments and unclear structure&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// GOOD&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;updateUserStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newStatus&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;updatedUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newStatus&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;logUserChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;updatedUser&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;saveUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;updatedUser&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;notifyUserStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;updatedUser&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/* Small helper functions */&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;setStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt; &lt;span class="c1"&gt;// pure, no side effects&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;logUserChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&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="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`User &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; status changed to &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&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="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;saveUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;database&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// isolated responsibility&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;notifyUserStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Always clear, specific action&lt;/span&gt;
  &lt;span class="nf"&gt;sendNotification&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Comments
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Comments should clarify intent, not describe what the code is doing. Code that explains itself through naming and structure is always better than one that needs constant explanation.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Avoid redundant comments that repeat what the code already states.&lt;/li&gt;
&lt;li&gt;Use variable and function names to explain logic instead of comments.&lt;/li&gt;
&lt;li&gt;Avoid detailed documentation (like JSDoc) unless you’re writing public APIs.&lt;/li&gt;
&lt;li&gt;Don’t describe or refer to code that exists elsewhere — if that code changes, the comment becomes outdated.&lt;/li&gt;
&lt;li&gt;Keep lines short, both for code and comments.&lt;/li&gt;
&lt;li&gt;Write comments only when they truly add value — for instance, when explaining complex regex patterns or specific design decisions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Testing
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Testing ensures that your code behaves as expected and that improvements or refactors don’t break existing functionality.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Writing tests guarantees reliability and reduces the risk of regressions.&lt;/li&gt;
&lt;li&gt;Don’t let fear of breaking something stop you from improving code — small refactors supported by tests keep systems healthy.&lt;/li&gt;
&lt;li&gt;Developers are responsible for code quality. QA should not be expected to find issues that proper testing would have caught.&lt;/li&gt;
&lt;li&gt;Use Test-Driven Development (TDD): write a failing test first, then implement code to make it pass, and finally refactor.&lt;/li&gt;
&lt;li&gt;Keep tests simple and focused, covering one scenario per test.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Code Review
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Code reviews help maintain quality and consistency across a team’s codebase. They are opportunities to learn, improve, and refine.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Code reviews should take almost as much time as writing the code itself.&lt;/li&gt;
&lt;li&gt;Focus reviews on clarity, naming, maintainability, and adherence to standards.&lt;/li&gt;
&lt;li&gt;Encourage continuous improvement — every review should leave the system cleaner and easier to maintain.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Clean code is a mindset and a responsibility.&lt;/strong&gt; Clear naming, small functions, meaningful comments, thorough testing, and careful reviews make code easier to understand, maintain, and extend. Start small — refactor a function, improve a name, or write a test — and over time, these habits lead to cleaner, safer, and more professional code that benefits everyone. 😊&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>frontend</category>
      <category>programming</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Essential SQL Commands: A Quick Reference Guide</title>
      <dc:creator>Diona Rodrigues</dc:creator>
      <pubDate>Fri, 18 Apr 2025 19:52:59 +0000</pubDate>
      <link>https://forem.com/dionarodrigues/essential-sql-commands-a-quick-reference-guide-59ff</link>
      <guid>https://forem.com/dionarodrigues/essential-sql-commands-a-quick-reference-guide-59ff</guid>
      <description>&lt;p&gt;&lt;strong&gt;I recently took some time to recap the SQL commands I use the most, and I decided to put together a few notes while I was at it. Nothing fancy—just a quick, practical list of the commands that come up often in my day-to-day work. Sharing them here in case they’re useful to anyone else who wants a simple reference or a refresher.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Tip: If you're looking to dive deep into MySQL, I highly recommend the &lt;a href="https://learning.oreilly.com/library/view/mysql-crash-course/9781098156824/" rel="noopener noreferrer"&gt;MySQL Crash Course by O'Reilly&lt;/a&gt; — it’s the one I took and found incredibly helpful.&lt;/p&gt;

&lt;h2&gt;
  
  
  Query Filtering &amp;amp; Sorting
&lt;/h2&gt;

&lt;p&gt;Commands for filtering and sorting the results of a &lt;code&gt;SELECT&lt;/code&gt; query.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;WHERE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Filters the records based on a condition&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SELECT * FROM users WHERE age &amp;gt; 20;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;AND / OR&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Combines multiple conditions&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SELECT * FROM users WHERE age &amp;gt; 20 AND name = 'John';&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ORDER BY&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Sorts the result set&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SELECT * FROM users ORDER BY age DESC;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;LIMIT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Limits the number of rows returned&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SELECT * FROM users LIMIT 10;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;BETWEEN&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Filters results within a specific range&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SELECT * FROM users WHERE age BETWEEN 20 AND 30;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;IN&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Filters results based on a set of values&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SELECT * FROM users WHERE name IN ('John', 'Jane');&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;LIKE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Searches for a pattern in a column&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SELECT * FROM users WHERE name LIKE 'J%';&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The * wildcard in SQL selects all columns from a table without listing them individually.&lt;/p&gt;

&lt;p&gt;Returns all columns from the users table (e.g., id, name, email, age, etc.).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In SQL, the &lt;code&gt;LIKE&lt;/code&gt; operator is commonly used to search for a specified pattern in a column. It's especially handy when you want to filter results based on partial matches.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Wildcard&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;th&gt;Matches&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;%&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Matches zero or more characters&lt;/td&gt;
&lt;td&gt;&lt;code&gt;name LIKE 'Jo%'&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;John, Joanna, Joe&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;_&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Matches exactly one character&lt;/td&gt;
&lt;td&gt;&lt;code&gt;name LIKE '_an'&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Dan, Jan, Pan&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Comparison Operators
&lt;/h2&gt;

&lt;p&gt;Used in &lt;code&gt;WHERE&lt;/code&gt; clauses to compare values or test specific conditions in SQL queries.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operator&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;=&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Equal to&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SELECT * FROM users WHERE age = 25;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;!=&lt;/code&gt; or &lt;code&gt;&amp;lt;&amp;gt;&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Not equal to&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SELECT * FROM users WHERE age != 25;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Greater than&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SELECT * FROM users WHERE age &amp;gt; 30;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Less than&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SELECT * FROM users WHERE age &amp;lt; 18;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;gt;=&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Greater than or equal to&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SELECT * FROM users WHERE age &amp;gt;= 21;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;=&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Less than or equal to&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SELECT * FROM users WHERE age &amp;lt;= 60;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;IS&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Compares with a specific value&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SELECT * FROM users WHERE is_verified IS TRUE;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;IS NULL&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A null value&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SELECT * FROM users WHERE phone IS NULL;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;IS NOT NULL&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A non-null value&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SELECT * FROM users WHERE phone IS NOT NULL;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;IN&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Matches a value in a list&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SELECT * FROM users WHERE name IN ('John', 'Jane');&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;NOT IN&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Doesn’t match a value in a list&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SELECT * FROM users WHERE age NOT IN (20, 30);&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;BETWEEN&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Within a range&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SELECT * FROM users WHERE age BETWEEN 20 AND 30;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;NOT BETWEEN&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Not within a range&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SELECT * FROM users WHERE age NOT BETWEEN 10 AND 15;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;LIKE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Matches a pattern&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SELECT * FROM users WHERE name LIKE 'J%';&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;NOT LIKE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Does not match a pattern&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SELECT * FROM users WHERE name NOT LIKE 'A%';&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  MySQL Data Types (Quick Reference)
&lt;/h2&gt;

&lt;p&gt;A concise guide to the different data types supported in MySQL, including numeric, string, date/time, and special types.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Data Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CHAR(n)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Fixed-length string (exact number of characters)&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;CHAR(3)&lt;/code&gt; can store &lt;code&gt;IRE&lt;/code&gt;, &lt;code&gt;GBR&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;VARCHAR(n)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Variable-length string, can hold up to a specified number of characters&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;VARCHAR(100)&lt;/code&gt; can store "Hello, World!"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;TEXT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Stores up to 65,535 characters (~64KB), typically used for large text&lt;/td&gt;
&lt;td&gt;"Lorem ipsum dolor sit amet..."&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;TINYTEXT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Stores up to 255 characters&lt;/td&gt;
&lt;td&gt;"Short text"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;MEDIUMTEXT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Stores up to 16,777,215 characters (~16MB)&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;LONGTEXT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Stores up to 4,294,967,295 characters (~4GB), used for very large text&lt;/td&gt;
&lt;td&gt;A very large article or file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;TINYINT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Small integers (1 byte, range: -128 to 127), often used for booleans&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;TINYINT&lt;/code&gt; can store &lt;code&gt;1&lt;/code&gt; for true or &lt;code&gt;0&lt;/code&gt; for false&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SMALLINT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Small integers (2 bytes)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;32767&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;MEDIUMINT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Medium-sized integers (3 bytes)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;8388607&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;INT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Standard integer (4 bytes)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;123456789&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;BIGINT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Large integers (8 bytes)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;123456789012345&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;BOOLEAN&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Alias for &lt;code&gt;TINYINT(1)&lt;/code&gt;, used for true/false values&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DECIMAL(m,d)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Fixed-point number with exact precision, ideal for money (&lt;code&gt;m&lt;/code&gt;, total digits - &lt;code&gt;d&lt;/code&gt; digits after the decimal)&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;DECIMAL(5,2)&lt;/code&gt; can store &lt;code&gt;999.99&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;FLOAT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Floating-point number with a decimal point that isn’t always in the same location&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;1.234&lt;/code&gt; or &lt;code&gt;12.34&lt;/code&gt; or &lt;code&gt;123.4.&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DATE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Date only (&lt;code&gt;YYYY-MM-DD&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;2025-04-14&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;TIME&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Time only (&lt;code&gt;HH:MM:SS&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;12:30:00&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DATETIME&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Date and time (&lt;code&gt;YYYY-MM-DD HH:MM:SS&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;2025-04-14 12:30:00&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;TIMESTAMP&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Stores the current date and time&lt;/td&gt;
&lt;td&gt;&lt;code&gt;2025-04-14 12:30:00&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;YEAR&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;4-digit year format&lt;/td&gt;
&lt;td&gt;&lt;code&gt;2025&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;JSON&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Stores JSON-formatted data (structured and queryable)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{"name": "John", "age": 30}&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ENUM&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A string object with a predefined list of allowed values.&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;ENUM('active', 'inactive', 'suspended')&lt;/code&gt; only accepts one of those values&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SET&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Similar to &lt;code&gt;ENUM&lt;/code&gt;, but allows multiple values from the predefined list to be selected.&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;SET('English','German','Spanish')&lt;/code&gt; allows we to add any or all of the languages&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This example demonstrates how various MySQL data types can be used when creating a &lt;code&gt;user_profile&lt;/code&gt; table:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;user_profile&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;user_id&lt;/span&gt;         &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="n"&gt;AUTO_INCREMENT&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;username&lt;/span&gt;        &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;email&lt;/span&gt;           &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;UNIQUE&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;account_status&lt;/span&gt;  &lt;span class="nb"&gt;ENUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'active'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'inactive'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'suspended'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="s1"&gt;'active'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;preferences&lt;/span&gt;     &lt;span class="n"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;is_verified&lt;/span&gt;     &lt;span class="nb"&gt;BOOLEAN&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="k"&gt;FALSE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;signup_date&lt;/span&gt;     &lt;span class="nb"&gt;DATETIME&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="k"&gt;CURRENT_TIMESTAMP&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Primary &amp;amp; Foreign Keys
&lt;/h2&gt;

&lt;p&gt;Used to uniquely identify records and establish relationships between tables in a database.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Concept&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;PRIMARY KEY&lt;/td&gt;
&lt;td&gt;Uniquely identifies each row in a table. Only one per table. Must be unique and not null.&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;user_id INT PRIMARY KEY&lt;/code&gt; ensures each user has a unique ID.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FOREIGN KEY&lt;/td&gt;
&lt;td&gt;A field that links to the PRIMARY KEY of another table, creating a relationship between them.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;user_id INT, FOREIGN KEY (user_id) REFERENCES users(user_id)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Here’s how to define primary and foreign keys when creating tables:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="n"&gt;AUTO_INCREMENT&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;order_id&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="n"&gt;AUTO_INCREMENT&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;order_total&lt;/span&gt; &lt;span class="nb"&gt;DECIMAL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="k"&gt;FOREIGN&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&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;Explanation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The users table uses &lt;code&gt;user_id&lt;/code&gt; as its &lt;code&gt;PRIMARY KEY&lt;/code&gt;. It guarantees that each user in the users table is uniquely identified. This ensures data integrity and prevents duplicate users.&lt;/li&gt;
&lt;li&gt;The orders table references &lt;code&gt;user_id&lt;/code&gt; from the users table as a &lt;code&gt;FOREIGN KEY&lt;/code&gt;, linking each order to a valid user. It creates a relationship between the orders and users tables.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What this gives us:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Relational structure&lt;/strong&gt;: We can easily connect a user to all their orders.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Referential integrity&lt;/strong&gt;: The database won’t allow an order to exist with a &lt;code&gt;user_id&lt;/code&gt; that doesn’t exist in the users table.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cleaner data&lt;/strong&gt;: No more orphaned orders or accidental inconsistencies.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;💡 With these keys in place, SQL joins become safer and more meaningful — because the database guarantees the connection between rows is valid.&lt;/p&gt;

&lt;h2&gt;
  
  
  Joins
&lt;/h2&gt;

&lt;p&gt;Commands to select data from multiple tables.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;INNER JOIN&lt;/code&gt; / &lt;code&gt;JOIN&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Returns records with matching values in both tables&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;LEFT JOIN&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Returns all records from the left table, and matching records from the right table&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;RIGHT JOIN&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Returns all records from the right table, and matching records from the left table&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;FULL OUTER JOIN&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Returns all rows from one table and the matching rows from a second table&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Example: Given two tables, one containing city names with their country codes and the other containing country names with their country codes, we can use SQL &lt;code&gt;JOIN&lt;/code&gt; operations to select and combine data from both tables.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cities table:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;city_name&lt;/th&gt;
&lt;th&gt;country_code&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;New York&lt;/td&gt;
&lt;td&gt;US&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Paris&lt;/td&gt;
&lt;td&gt;FR&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tokyo&lt;/td&gt;
&lt;td&gt;JP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Los Angeles&lt;/td&gt;
&lt;td&gt;US&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sydney&lt;/td&gt;
&lt;td&gt;AU&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dublin&lt;/td&gt;
&lt;td&gt;IR&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Countries table:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;country_name&lt;/th&gt;
&lt;th&gt;country_code&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ireland&lt;/td&gt;
&lt;td&gt;IR&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Japan&lt;/td&gt;
&lt;td&gt;JP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Australia&lt;/td&gt;
&lt;td&gt;AU&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Italy&lt;/td&gt;
&lt;td&gt;IT&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Examples Using Different Joins:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;city_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;co&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;country_name&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;cities&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;
&lt;span class="k"&gt;INNER&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;countries&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;co&lt;/span&gt;
&lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;country_code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;co&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;country_code&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This uses &lt;code&gt;c&lt;/code&gt; as the alias for &lt;code&gt;cities&lt;/code&gt; and &lt;code&gt;co&lt;/code&gt; for &lt;code&gt;countries&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We can replace &lt;code&gt;INNER JOIN&lt;/code&gt; in the query above with &lt;code&gt;LEFT JOIN&lt;/code&gt;, &lt;code&gt;RIGHT JOIN&lt;/code&gt;, or use a &lt;code&gt;FULL OUTER JOIN&lt;/code&gt; (with a workaround in MySQL) to see different results based on the type of join.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;INNER JOIN&lt;/code&gt;&lt;/strong&gt;: Returns only the cities with a matching &lt;code&gt;country_code&lt;/code&gt; in both tables.&lt;br&gt;
&lt;strong&gt;Result:&lt;/strong&gt; Tokyo/Japan, and Sydney/Australia and Dublin/Ireland.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;LEFT JOIN&lt;/code&gt;&lt;/strong&gt;: Returns all the rows from the left table (&lt;code&gt;cities&lt;/code&gt;), and the matching rows from the right table (&lt;code&gt;countries&lt;/code&gt;). If there is no match in the right table, the query will return &lt;code&gt;NULL&lt;/code&gt; for the columns from the right table.&lt;br&gt;
&lt;strong&gt;Result:&lt;/strong&gt; All cities, but New York, Paris, and Los Angeles with &lt;code&gt;NULL&lt;/code&gt; in the &lt;code&gt;country_name&lt;/code&gt;column.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;RIGHT JOIN&lt;/code&gt;&lt;/strong&gt;: Returns all rows from the right table (&lt;code&gt;countries&lt;/code&gt;) and the matching rows from the left table (&lt;code&gt;cities&lt;/code&gt;).&lt;br&gt;
&lt;strong&gt;Result:&lt;/strong&gt; Dublin, Tokyo and Sydney with their country names and &lt;code&gt;NULL&lt;/code&gt; as the &lt;code&gt;city_name&lt;/code&gt; for Italy.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Database Management Commands
&lt;/h2&gt;

&lt;p&gt;These commands are used for creating, managing, and deleting databases and tables.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CREATE DATABASE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Creates a new database&lt;/td&gt;
&lt;td&gt;&lt;code&gt;CREATE DATABASE mydb;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;USE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Selects a database to use&lt;/td&gt;
&lt;td&gt;&lt;code&gt;USE mydb;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DROP DATABASE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deletes a database&lt;/td&gt;
&lt;td&gt;&lt;code&gt;DROP DATABASE mydb;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CREATE TABLE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Creates a new table&lt;/td&gt;
&lt;td&gt;&lt;code&gt;CREATE TABLE users (id INT, name VARCHAR(100));&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DROP TABLE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deletes a table&lt;/td&gt;
&lt;td&gt;&lt;code&gt;DROP TABLE users;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ALTER TABLE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Modifies an existing table&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ALTER TABLE users ADD COLUMN age INT;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SHOW TABLES&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Displays a list of all tables in the current database&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SHOW TABLES;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DESCRIBE/EXPLAIN&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Displays structure of a table (columns, types, etc.)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;DESCRIBE users;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Data Manipulation Commands
&lt;/h2&gt;

&lt;p&gt;Commands to insert, update, delete, and select data in tables.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;INSERT INTO&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Inserts new rows into a table&lt;/td&gt;
&lt;td&gt;&lt;code&gt;INSERT INTO users (name, age) VALUES ('John', 25);&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SELECT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Retrieves data from a table&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SELECT * FROM users;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;UPDATE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Updates existing rows in a table&lt;/td&gt;
&lt;td&gt;&lt;code&gt;UPDATE users SET age = 26 WHERE id = 1;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DELETE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deletes rows from a table&lt;/td&gt;
&lt;td&gt;&lt;code&gt;DELETE FROM users WHERE id = 1;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;TRUNCATE TABLE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deletes all rows in a table (without logging individual row deletions)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;TRUNCATE TABLE users;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Inserting multiple rows at once:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;VALUES&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'John'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Jane'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Bob'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Alice'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;28&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Aggregate Functions
&lt;/h2&gt;

&lt;p&gt;Functions that return aggregated values such as sums, averages, counts, etc.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;COUNT()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Returns the number of rows that match a query&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SELECT COUNT(*) FROM users WHERE age &amp;gt; 20;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SUM()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Returns the sum of a numeric column&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SELECT SUM(age) FROM users;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;AVG()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Returns the average value of a numeric column&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SELECT AVG(age) FROM users;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;MIN()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Returns the minimum value of a column&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SELECT MIN(age) FROM users;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;MAX()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Returns the maximum value of a column&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SELECT MAX(age) FROM users;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Transactions
&lt;/h2&gt;

&lt;p&gt;Commands to manage database transactions and maintain data integrity.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;START TRANSACTION&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Begins a new transaction&lt;/td&gt;
&lt;td&gt;&lt;code&gt;START TRANSACTION;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;COMMIT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Commits the current transaction&lt;/td&gt;
&lt;td&gt;&lt;code&gt;COMMIT;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ROLLBACK&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Rolls back the current transaction&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ROLLBACK;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Here’s a simple example demonstrating how transactions work:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;START&lt;/span&gt; &lt;span class="n"&gt;TRANSACTION&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;accounts&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;user_id&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="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;accounts&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- If everything is fine, then run:&lt;/span&gt;
&lt;span class="c1"&gt;-- COMMIT;&lt;/span&gt;

&lt;span class="c1"&gt;-- If something goes wrong, then run:&lt;/span&gt;
&lt;span class="c1"&gt;-- ROLLBACK;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explanation:&lt;/strong&gt; This example simulates a money transfer between two users. The &lt;code&gt;START TRANSACTION&lt;/code&gt; begins a transaction block. If both &lt;code&gt;UPDATE&lt;/code&gt; statements succeed, &lt;code&gt;COMMIT&lt;/code&gt; saves the changes. If an error occurs (e.g., user_id 2 doesn’t exist), &lt;code&gt;ROLLBACK&lt;/code&gt; undoes both updates to maintain data integrity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;SQL is an incredibly powerful tool for interacting with databases, and understanding the essential commands is key to writing efficient and effective queries. By revisiting and practicing these commonly used commands, such as those for filtering, sorting, joining tables, and managing transactions, we can significantly improve our workflow and avoid common pitfalls. 😊&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>mysql</category>
      <category>database</category>
      <category>sql</category>
    </item>
    <item>
      <title>Redux Toolkit Advanced: Scaling Redux Toolkit for Large Applications</title>
      <dc:creator>Diona Rodrigues</dc:creator>
      <pubDate>Sun, 13 Apr 2025 20:12:09 +0000</pubDate>
      <link>https://forem.com/dionarodrigues/redux-toolkit-advanced-scaling-redux-toolkit-for-large-applications-gb</link>
      <guid>https://forem.com/dionarodrigues/redux-toolkit-advanced-scaling-redux-toolkit-for-large-applications-gb</guid>
      <description>&lt;p&gt;&lt;strong&gt;Redux Toolkit (RTK) has revolutionized state management in React applications by simplifying boilerplate and enforcing best practices. While basic usage is straightforward, scaling Redux effectively in large applications requires a deeper understanding of advanced concepts — and that’s exactly what you’ll learn in this article.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you're new to Redux Toolkit, I covered the &lt;a href="https://dev.to/dionarodrigues/redux-toolkit-fundamentals-simplifying-state-management-41m4"&gt;RTK fundamentals in a previous article&lt;/a&gt;, including why it's the officially recommended approach, its advantages, and how to use its main APIs to create a basic store.&lt;/p&gt;

&lt;p&gt;In this article, we'll explore powerful Redux Toolkit techniques to streamline state management in complex projects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Triggering updates across multiple slices using &lt;code&gt;createAction&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Managing normalized state efficiently with &lt;code&gt;createSlice&lt;/code&gt; and &lt;code&gt;createEntityAdapter&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Optimizing data access with &lt;code&gt;createSelector&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Enhancing reusability with custom hooks leveraging &lt;code&gt;useSelector&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By mastering these techniques, you'll gain greater flexibility and maintainability in your Redux applications, ensuring they scale effectively. Let’s dive in! 🚀&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction to Advanced Redux Toolkit Techniques
&lt;/h2&gt;

&lt;p&gt;Throughout this article, I'll walk you through key techniques using code snippets from a straightforward yet comprehensive project I built to showcase all the core features of Redux Toolkit (RTK) mentioned above. You're welcome to explore the full &lt;a href="https://github.com/dionarodrigues/labs/tree/master/advanced-rtk-architecture" rel="noopener noreferrer"&gt;repository on GitHub&lt;/a&gt; for a deeper dive into the files.&lt;/p&gt;

&lt;p&gt;The aim here isn’t to overwhelm you with unnecessary complexity but to demonstrate with 7 practical steps how to start designing an efficient architecture for large-scale applications using RTK. By the end of this article, you'll have valuable insights into how to scale and structure future projects with greater efficiency and clarity.&lt;/p&gt;

&lt;h3&gt;
  
  
  Before we start
&lt;/h3&gt;

&lt;p&gt;Before diving into the techniques, I want to provide some context so you can better understand the approach we're taking and absorb the information more effectively.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let’s imagine a page that lists airlines based on the selected region. The page includes a header with links to different regions (e.g., Europe, America, Asia). Each time a region is selected, we fetch airline data from an API based on that region.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6naructc1wlo0prb5203.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6naructc1wlo0prb5203.png" alt="Screenshot of the project page showing a list of European Airlines. Each airline is a different card containing name, foundation and country" width="800" height="515"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The returned data contains a list of airlines structured like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;endpoint:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;http://localhost:&lt;/span&gt;&lt;span class="mi"&gt;5002&lt;/span&gt;&lt;span class="err"&gt;/airlines/europe&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;101&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Air France"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"foundation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1933&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"country"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"France"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;102&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Ryanair"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"foundation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1984&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"country"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;202&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Ireland"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check out the &lt;a href="https://github.com/dionarodrigues/labs/blob/master/advanced-rtk-architecture/server/data.json" rel="noopener noreferrer"&gt;full JSON file here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The goal is to fetch this data, normalize it, and update the relevant slices in our Redux store. Here's the structure of our Redux store:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;store
├── airlines
├── countries
├── pointers

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

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc0vepzt4zmffe2l3nvge.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc0vepzt4zmffe2l3nvge.png" alt="Screenshot of the project's redux store showing the data organized by airlines, countries and pointers" width="800" height="708"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The airlines slice will store a list of airlines, where each entry will look like &lt;code&gt;{ id: 101, name: 'Air France', foundation: 1933 }&lt;/code&gt;, for example. The countries slice will follow a similar structure for countries &lt;code&gt;{ id: 201, name: France }&lt;/code&gt;. The pointers slice will store relationships between airlines and countries, such as &lt;code&gt;{ airline_id: 101, country_id: 201 }&lt;/code&gt;. These pointers will allow us to easily reference data from other slices.&lt;/p&gt;

&lt;p&gt;Once all the data is in the store, we'll use RTK selectors and custom hooks to get the data to be used by the UI components.&lt;/p&gt;

&lt;p&gt;Now we are ready! 😄&lt;/p&gt;

&lt;h2&gt;
  
  
  1- Handling Cross-Slice Actions with &lt;code&gt;createAction&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Sometimes, different slices need to react to the same event — like syncing or resetting shared data. &lt;strong&gt;With &lt;code&gt;createAction&lt;/code&gt;, you can define generic actions that are not tied to a specific slice. These actions carry a payload containing the data to be updated or cleared, allowing any reducer to respond to them.&lt;/strong&gt; This approach enables clean, modular cross-slice updates without creating dependencies between the slices.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// actions.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createAction&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@reduxjs/toolkit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// `updateEntities` will be used to trigger a state update in the reducer&lt;/span&gt;
&lt;span class="c1"&gt;// It will carry the payload that contains the data to be updated in the store&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;updateEntities&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createAction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;UPDATE_ENTITIES&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// `cleanUpEntities` will be dispatched to clear or reset the data&lt;/span&gt;
&lt;span class="c1"&gt;// This can be useful when you want to remove data from the store, e.g., on component unmount or after a request is completed&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cleanUpEntities&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createAction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;CLEAN_UP_ENTITIES&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, two shared actions are created: &lt;code&gt;updateEntities&lt;/code&gt; for syncing entity data and &lt;code&gt;cleanUpEntities&lt;/code&gt; for clearing it. Other slices can import and respond to these actions in their reducers without depending on each other.&lt;/p&gt;

&lt;h2&gt;
  
  
  2- Creating Slices That Respond to Shared Actions
&lt;/h2&gt;

&lt;p&gt;Now that we've defined shared actions (&lt;code&gt;updateEntities&lt;/code&gt; and &lt;code&gt;cleanUpEntities&lt;/code&gt;), let's see how to create slices that respond to them. We'll use &lt;code&gt;createSlice&lt;/code&gt; and &lt;code&gt;createEntityAdapter&lt;/code&gt; to manage normalized entity state for each slice (airlines, countries and pointers). For a deeper dive into these APIs, check out my &lt;a href="https://dionarodrigues.dev/blog/redux-toolkit-fundamentals-simplifying-state-management" rel="noopener noreferrer"&gt;RTK fundamentals article&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✈️ Airlines Slice
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// airlinesSlice.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createSlice&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;createEntityAdapter&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@reduxjs/toolkit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;updateEntities&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cleanUpEntities&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@store/actions&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Create an entity adapter to help manage normalized airline data&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;airlinesAdapter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createEntityAdapter&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Generate the initial state using the adapter&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;initialState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;airlinesAdapter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getInitialState&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Create the airlines slice&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;airlinesSlice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createSlice&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;airlines&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Unique slice name&lt;/span&gt;
  &lt;span class="nx"&gt;initialState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Initial normalized state&lt;/span&gt;
  &lt;span class="na"&gt;reducers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="c1"&gt;// No local reducers needed in this example&lt;/span&gt;

  &lt;span class="c1"&gt;// Use extraReducers to handle shared, cross-slice actions&lt;/span&gt;
  &lt;span class="na"&gt;extraReducers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;builder&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;builder&lt;/span&gt;
      &lt;span class="c1"&gt;// When the updateEntities action is dispatched with a payload containing airline data,&lt;/span&gt;
      &lt;span class="c1"&gt;// the slice will replace the current state with the new set of airlines&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;updateEntities&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;airlines&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;airlinesAdapter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;airlines&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="c1"&gt;// When the cleanUpEntities action is dispatched (which doesn't need a payload),&lt;/span&gt;
      &lt;span class="c1"&gt;// the slice will remove all airlines from the state&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cleanUpEntities&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;airlinesAdapter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Export the reducer to be used in the store&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;airlinesSlice&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reducer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the airlines slice uses &lt;code&gt;extraReducers&lt;/code&gt; to respond to two shared actions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;updateEntities&lt;/code&gt;: If &lt;code&gt;action.payload.airlines&lt;/code&gt; is present, the slice updates its entire entity collection using &lt;code&gt;setAll&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cleanUpEntities&lt;/code&gt;: Clears all airlines from the state using removeAll.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This pattern makes it easy for multiple slices to react to a single source of truth or cleanup event.&lt;br&gt;
A common use case for &lt;code&gt;cleanUpEntities&lt;/code&gt; is when a component unmounts—for example, to clear out data that's no longer needed once a page or view is closed. This helps keep your store clean and avoids persisting stale data across views.&lt;/p&gt;
&lt;h3&gt;
  
  
  Countries &amp;amp; 📍 Pointers slices
&lt;/h3&gt;

&lt;p&gt;The countries slice follows the exact same structure as airlines, simply replacing the key words. Check out the &lt;a href="https://github.com/dionarodrigues/labs/blob/master/advanced-rtk-architecture/src/features/countries/countriesSlice.js" rel="noopener noreferrer"&gt;code here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The pointers slice is nearly identical too, but instead of calling &lt;code&gt;setAll&lt;/code&gt;, it uses &lt;code&gt;setOne&lt;/code&gt; — since it's likely managing a single pointer entity rather than a list:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pointers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;pointersAdapter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setOne&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pointers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The pointers slice works a bit differently (&lt;a href="https://github.com/dionarodrigues/labs/blob/master/advanced-rtk-architecture/src/features/pointers/pointersSlice.js" rel="noopener noreferrer"&gt;code here&lt;/a&gt;). Instead of receiving an array of pointer entities, it expects them to be grouped by region, like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pointers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;region&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;mapping&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="na"&gt;airline_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;101&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;country_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;201&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this structure, the region name becomes the entity ID, and each entity includes a mapping property containing the list of pointers for that region. This design allows the store to hold pointers for multiple regions at the same time, offering greater flexibility when managing localized data.&lt;/p&gt;

&lt;p&gt;Despite this small variation, the slice still integrates smoothly with the shared action system — highlighting how adaptable this pattern is for handling cross-slice updates with diverse data shapes.&lt;/p&gt;

&lt;h2&gt;
  
  
  3- Setting Up the Store with Our Slices
&lt;/h2&gt;

&lt;p&gt;Now that we have our individual slices defined (airlines, countries, and pointers), the next step is to combine them into a single Redux store. This is done using &lt;code&gt;configureStore&lt;/code&gt; from Redux Toolkit.&lt;/p&gt;

&lt;p&gt;By registering each slice reducer under its own key, we create a modular structure where each slice manages its own section of the state. Here's how the store is set up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// store.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;configureStore&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@reduxjs/toolkit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Import slice reducers&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;airlinesReducer&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@features/airlines/airlinesSlice&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;countriesReducer&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@features/countries/countriesSlice&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;pointersReducer&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@features/pointers/pointersSlice&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Create and configure the Redux store&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;configureStore&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;reducer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Each slice manages its own section of the state&lt;/span&gt;
    &lt;span class="na"&gt;airlines&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;airlinesReducer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;countries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;countriesReducer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;pointers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;pointersReducer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Connecting the Redux Store to React
&lt;/h3&gt;

&lt;p&gt;Note: To make the Redux store available throughout your React app, wrap your root component with the Provider component from react-redux. This allows any component in the tree to access the store using hooks like &lt;code&gt;useSelector&lt;/code&gt; and &lt;code&gt;useDispatch&lt;/code&gt; that we will see soon.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Provider&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-redux&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@store/store&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;createRoot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;root&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;StrictMode&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Provider&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Router&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Router&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Provider&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/StrictMode&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4- Sending Data to the Store with dispatch and Shared Actions
&lt;/h2&gt;

&lt;p&gt;Now that our Redux setup is in place, let’s see how to send data to the store using a real-world example. In this case, we have a component called Airlines that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Retrieves a region from the URL using &lt;code&gt;useParams&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Fetches airline data based on that region.&lt;/li&gt;
&lt;li&gt;Normalizes the response using a custom function called &lt;code&gt;normalizeData()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Dispatches the &lt;code&gt;updateEntities&lt;/code&gt; action to populate the store.&lt;/li&gt;
&lt;li&gt;Cleans up the state on unmount using &lt;code&gt;cleanUpEntities&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s a simplified version of how it works (&lt;a href="https://github.com/dionarodrigues/labs/blob/master/advanced-rtk-architecture/src/pages/Airlines.jsx" rel="noopener noreferrer"&gt;full code here&lt;/a&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&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="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useDispatch&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-redux&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useParams&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-router-dom&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;updateEntities&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cleanUpEntities&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@store/actions&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;normalizeData&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@utils/normalizer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Airports&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;dispatch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useDispatch&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;region&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useParams&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nf"&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="c1"&gt;// Fetch data based on the region&lt;/span&gt;
    &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`http://localhost:5002/airlines/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;region&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="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;res&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;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Normalize and dispatch it to the store&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;normalizedData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;normalizeData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;region&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;updateEntities&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;normalizedData&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// Cleanup the store when the component unmounts&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="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;cleanUpEntities&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;dispatch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;region&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* render something */&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;✨ Quick Note on the normalizeData Function:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When the API returns data, it usually comes as a nested list of airlines, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;endpoint:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;http://localhost:&lt;/span&gt;&lt;span class="mi"&gt;5002&lt;/span&gt;&lt;span class="err"&gt;/airlines/europe&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;101&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Air France"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"foundation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1933&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"country"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"France"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To better structure this for Redux, we normalize the response into a flat format using &lt;code&gt;normalizeData()&lt;/code&gt; (&lt;a href="https://github.com/dionarodrigues/labs/blob/master/advanced-rtk-architecture/src/utils/normalizer.js" rel="noopener noreferrer"&gt;code here&lt;/a&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;airlines&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="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;101&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Air France&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;foundation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1933&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;countries&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="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;France&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;pointers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;europe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;mapping&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="na"&gt;airline_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;101&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;country_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;201&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This normalized object is then passed as the payload of our &lt;code&gt;updateEntities&lt;/code&gt; action. Thanks to the way each slice is set up, they will automatically update their state with the relevant portion of the payload. Pretty cool, right?&lt;/p&gt;

&lt;h2&gt;
  
  
  5- Optimizing State Access with Selectors
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Selectors allow us to efficiently retrieve specific pieces of data from the Redux store, minimizing unnecessary re-renders by memoizing results. This optimization improves both performance and maintainability of the codebase.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this section, we'll explore how selectors are defined and used, with an example focused on the airlines feature.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating the Selectors
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;createSelector&lt;/code&gt; from Redux Toolkit creates memoized selectors that only recompute when their inputs change. This helps avoid unnecessary recalculations and re-renders, improving performance, especially with complex or nested state.&lt;/p&gt;

&lt;h4&gt;
  
  
  Airlines selectors
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// airlinesSelectors.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createSelector&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@reduxjs/toolkit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;airlinesAdapter&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./airlinesSlice&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Get the default selector from the airlines slice&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;selectById&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;selectAirlinesById&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;airlinesAdapter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSelectors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;airlines&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Create a selector to retrieve an airline by its ID&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;selectAirline&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;airlineId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nf"&gt;selectAirlinesById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;airlineId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Use createSelector to transform the data (e.g., extracting the name of the airline)&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;selectAirlineName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createSelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;selectAirline&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;airline&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;airline&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Extract the foundation of the airline&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;selectAirlineFoundation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createSelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;selectAirline&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;airline&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;airline&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;foundation&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;selectAirline&lt;/code&gt;: Retrieves an airline by its unique ID from the store.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;selectAirlineName&lt;/code&gt;: Memoized selector that returns the airline's name and prevents unnecessary re-renders.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;selectAirlineFoundation&lt;/code&gt;: Memoized selector that returns the foundation year and avoids re-renders when unrelated state changes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Countries selectors
&lt;/h4&gt;

&lt;p&gt;Selectors for countries are very similar to the ones we created for airlines. You can check them out &lt;a href="https://github.com/dionarodrigues/labs/blob/master/advanced-rtk-architecture/src/features/countries/countriesSelectors.js" rel="noopener noreferrer"&gt;here&lt;/a&gt; for reference.&lt;/p&gt;

&lt;h4&gt;
  
  
  Pointers selectors
&lt;/h4&gt;

&lt;p&gt;For the pointers feature, we'll combine multiple selectors and transform data as part of the selection process. This enables us to retrieve and format data efficiently. Here's an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// pointersSelectors.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createSelector&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@reduxjs/toolkit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;pointersAdapter&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./pointersSlice&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;selectAirlineName&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@features/airlines/airlinesSelectors&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Get the basic selector from pointersSlice&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;selectById&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;selectPointerById&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pointersAdapter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSelectors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pointers&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Select pointers based on the region (pointersId)&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;selectPointers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pointersId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nf"&gt;selectPointerById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pointersId&lt;/span&gt;&lt;span class="p"&gt;)?.&lt;/span&gt;&lt;span class="nx"&gt;mapping&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Select pointers sorted alphabetically by airline name&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;selectPointersByAlphabeticalOrder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createSelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pointersId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;selectPointers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pointersId&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pointers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;pointers&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;pointers&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&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;nameA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;selectAirlineName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;airline_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&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;nameB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;selectAirlineName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;airline_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;??&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="nx"&gt;nameA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;localeCompare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nameB&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, we are combining two selectors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;selectPointers&lt;/code&gt;: This selector retrieves the list of pointers based on the region (identified by pointersId).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;selectPointersByAlphabeticalOrder&lt;/code&gt;: This custom selector sorts the pointers alphabetically by airline name, making the data more useful for display purposes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By using &lt;code&gt;createSelector&lt;/code&gt;, we not only combine and format the data but also ensure performance optimization by memoizing the results. This prevents unnecessary recalculations and improves the efficiency of the application.&lt;/p&gt;

&lt;h2&gt;
  
  
  6- Custom Hooks for Redux State
&lt;/h2&gt;

&lt;p&gt;As your application grows, accessing state directly in components using useSelector can lead to repetitive and hard-to-read code. &lt;strong&gt;To keep components clean, focused, and maintainable, we can use custom hooks to encapsulate state access logic&lt;/strong&gt;. This separation of concerns allows your components to concentrate on rendering and interaction, rather than worrying about how data is retrieved from the store.&lt;/p&gt;

&lt;p&gt;For example, instead of writing this in every component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;airlineName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSelector&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;selectAirlineName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;airlineId&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can define a simple custom hook:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useAirlineName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;airlineId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nf"&gt;useSelector&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;selectAirlineName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;airlineId&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then use it in a component like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;airlineName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useAirlineName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;airlineId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This keeps components cleaner, more concise, and easier to test.&lt;/p&gt;

&lt;h3&gt;
  
  
  Airlines custom hooks
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// useAirlines.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useSelector&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-redux&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;selectAirlineName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;selectAirlineFoundation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@features/airlines/airlinesSelectors&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Select airline name&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useAirlineName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;airlineId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nf"&gt;useSelector&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;selectAirlineName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;airlineId&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="c1"&gt;// Select airline foundation&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useAirlineFoundation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;airlineId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nf"&gt;useSelector&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;selectAirlineFoundation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;airlineId&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Countries custom hooks
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// useCountries.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useSelector&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-redux&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;selectCountryName&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@features/countries/countriesSelectors&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Select country name&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useCountryName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;countryId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nf"&gt;useSelector&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;selectCountryName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;countryId&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Pointers custom hooks
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// usePointers.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useSelector&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-redux&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;selectPointersByAlphabeticalOrder&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@features/pointers/pointersSelectors&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Select all pointers by Alphabetical order&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;usePointersByAlphabeticalOrder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pointersId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nf"&gt;useSelector&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;selectPointersByAlphabeticalOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pointersId&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Beyond Simple Hooks
&lt;/h3&gt;

&lt;p&gt;While the examples above show simple wrappers around selectors, custom hooks can be more powerful:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Combine multiple selectors&lt;/li&gt;
&lt;li&gt;Include conditional logic&lt;/li&gt;
&lt;li&gt;Provide computed or derived values&lt;/li&gt;
&lt;li&gt;Handle side effects or local state in addition to global Redux state&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By building these abstractions into hooks, we create consistent, reusable patterns across the app that improve maintainability and scalability.&lt;/p&gt;

&lt;h2&gt;
  
  
  7- Using Custom Hooks to Display Data in Components
&lt;/h2&gt;

&lt;p&gt;Now that we've created custom hooks to access the Redux state, we can use them to select and display the data cleanly in our UI components. Below are two components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Airlines&lt;/strong&gt;: fetches and normalizes the data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AirlineCard&lt;/strong&gt;: consumes the data using custom hooks and renders it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;Airlines&lt;/code&gt; component below is a simplified version of a more complete one available in &lt;a href="https://github.com/dionarodrigues/labs/blob/master/advanced-rtk-architecture/src/pages/Airlines.jsx" rel="noopener noreferrer"&gt;my GitHub repository&lt;/a&gt;. This version is meant to demonstrate how we can retrieve the pointers using a custom hook and pass their associated IDs down to the &lt;code&gt;AirlineCard&lt;/code&gt; component. Each &lt;code&gt;AirlineCard&lt;/code&gt; then uses these IDs to select and display specific pieces of data from the Redux store through dedicated custom hooks.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Airlines.jsx&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useParams&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-router-dom&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;usePointersByAlphabeticalOrder&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@hooks/usePointers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;AirlineCard&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@components/AirlineCard&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Airlines&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;region&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useParams&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="c1"&gt;// Get the pointers by using the region as ID&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pointers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;usePointersByAlphabeticalOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;region&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// If there are no pointers (empty array), return null&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;pointers&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="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="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&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;region&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Display an AirlineCard for each pointers entity ({ airline_id: 101, country_id: 201 }) */&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;pointers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;airline_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;country_id&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;AirlineCard&lt;/span&gt;
          &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&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;airline_id&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;country_id&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;airlineId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;airline_id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="nx"&gt;countryId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;country_id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;))}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we have the &lt;code&gt;AirlineCard&lt;/code&gt; component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// AirlineCard.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useAirlineName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useAirlineFoundation&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@hooks/useAirlines&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useCountryName&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@hooks/useCountries&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;AirlineCard&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;airlineId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;countryId&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;airlineName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useAirlineName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;airlineId&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;airlineFoundation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useAirlineFoundation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;airlineId&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;countryName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCountryName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;countryId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h2&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;airlineName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h2&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ul&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;li&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;strong&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Foundation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/strong&amp;gt; {airlineFoundation&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/li&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;li&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;strong&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Country&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/strong&amp;gt; {countryName&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/li&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ul&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this setup, the &lt;code&gt;Airlines&lt;/code&gt; component retrieves the data for airlines by calling a custom hook (&lt;code&gt;usePointersByAlphabeticalOrder&lt;/code&gt;) and passes the necessary IDs (such as &lt;code&gt;airlineId&lt;/code&gt; and &lt;code&gt;countryId&lt;/code&gt;) down to the &lt;code&gt;AirlineCard&lt;/code&gt;. Each &lt;code&gt;AirlineCard&lt;/code&gt; then uses custom hooks like &lt;code&gt;useAirlineName&lt;/code&gt;, &lt;code&gt;useAirlineFoundation&lt;/code&gt;, and &lt;code&gt;useCountryName&lt;/code&gt; to pull the corresponding data from the Redux store.&lt;/p&gt;

&lt;p&gt;This method helps to keep the components clean and ensures that we only fetch the necessary data in a way that is easy to manage and maintain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion: 🚀 Wrapping Up Advanced Redux Toolkit Techniques
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;In this article, we've explored advanced Redux Toolkit techniques that enable you to scale and optimize state management in large React applications. By leveraging features like &lt;code&gt;createAction&lt;/code&gt;, &lt;code&gt;createSlice&lt;/code&gt;, &lt;code&gt;createEntityAdapter&lt;/code&gt;, &lt;code&gt;createSelector,&lt;/code&gt; and custom hooks, you can manage complex state efficiently, improve performance, and maintain modularity in your projects.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As your application grows, these techniques will help you streamline your state management, making it easier to manage cross-slice actions, normalize data, optimize data access, and create reusable hooks. Happy coding, and enjoy scaling your projects! 🙌🎉&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>react</category>
      <category>redux</category>
    </item>
    <item>
      <title>Redux Toolkit Fundamentals: Simplifying State Management</title>
      <dc:creator>Diona Rodrigues</dc:creator>
      <pubDate>Tue, 01 Apr 2025 09:38:02 +0000</pubDate>
      <link>https://forem.com/dionarodrigues/redux-toolkit-fundamentals-simplifying-state-management-41m4</link>
      <guid>https://forem.com/dionarodrigues/redux-toolkit-fundamentals-simplifying-state-management-41m4</guid>
      <description>&lt;p&gt;&lt;strong&gt;If you have ever used Redux, you probably remember how complicated it could get—setting up the store, writing actions and reducers, and making sure everything stayed immutable. It required a lot of upfront decisions, which made state management feel overwhelming. Luckily, Redux Toolkit (RTK) changes the game! It streamlines setup, enforces best practices, and comes with built-in tools like Immer for seamless immutable updates, Redux Thunk for handling async logic, and automatic store configuration. With RTK, managing state is easier, cleaner, and way less frustrating.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this article, we'll cover Redux Toolkit fundamentals—its core concepts (like &lt;code&gt;configureStore&lt;/code&gt; and &lt;code&gt;createSlice&lt;/code&gt;), how it works, and why it's the standard for Redux development. Whether you're new or experienced, RTK is the best approach to Redux development. Check out this next article called &lt;a href="https://dev.to/dionarodrigues/redux-toolkit-advanced-scaling-redux-toolkit-for-large-applications-gb"&gt;Redux Toolkit Advanced: Scaling Redux Toolkit for Large Applications&lt;/a&gt;, where we'll dive into advanced topics like shared actions across slices, combined selectors and custom hooks.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Redux, BTW?
&lt;/h2&gt;

&lt;p&gt;Before diving into Redux Toolkit, let’s quickly revisit Redux itself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Redux is a state management library that helps us manage global state in JavaScript applications, especially but not only in React. It uses a centralised state management pattern, ensuring structured data flow and predictable state updates.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;At its core, &lt;a href="https://redux.js.org/understanding/thinking-in-redux/three-principles" rel="noopener noreferrer"&gt;Redux is built around three main principles&lt;/a&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Single Source of Truth&lt;/strong&gt;: The global application state is stored in a single Redux store, making it easier to manage, debug, and track state changes throughout the app.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;State is Read-Only&lt;/strong&gt;: The state cannot be modified directly. Instead, we dispatch actions to describe changes, ensuring that updates always follow a predictable and traceable flow.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Changes are Made with Pure Functions&lt;/strong&gt;: Instead of mutating state directly, reducers process actions and return a new state, ensuring predictable updates.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;While Redux provides simple, but powerful state management, it requires a lot of boilerplate code and manual setup—which is where Redux Toolkit comes in to simplify things. Let’s see how! 🚀&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing Redux Toolkit (RTK)
&lt;/h2&gt;

&lt;p&gt;Let’s briefly summarise key RTK concepts before exploring them in practice.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Redux Toolkit (RTK) is the official, recommended approach to writing Redux logic, designed to simplify development and minimize boilerplate.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this article, we’ll dive into three basic core RTK concepts and use them to create a simple, functional ToDo list in React.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;configureStore&lt;/strong&gt;: A wrapper around Redux’s &lt;code&gt;createStore&lt;/code&gt; that simplifies store setup. It automatically combines slice reducers, includes redux-thunk by default (for asynchronous logic), enables the Redux DevTools Extension, and allows custom middleware.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;createSlice&lt;/strong&gt;: A higher-level abstraction that combines reducers and actions into a single API. It takes a slice name, an initial state, and an object of reducer functions, automatically generating the corresponding reducer, action creators, and action types.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;createEntityAdapter&lt;/strong&gt;: normalizes data, generates reusable reducers, and improves performance by simplifying CRUD operations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are the main RTK concepts we’ll be using in this article as we explore how to implement them in practice. They simplify Redux development a lot and help manage state more efficiently. If you’d like to explore additional features, you can check the &lt;a href="https://redux-toolkit.js.org/introduction/getting-started#whats-included" rel="noopener noreferrer"&gt;complete RTK API list&lt;/a&gt; in the official Redux Toolkit documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Redux Toolkit in practice: Building a simple To-Do list
&lt;/h2&gt;

&lt;p&gt;In this section, we'll explore how to use Redux Toolkit (RTK) in a practical scenario by building a simple to-do list application in React. From setting up a Redux store with &lt;code&gt;configureStore&lt;/code&gt; to creating slices with &lt;code&gt;createSlice&lt;/code&gt; and managing state efficiently, this guide will walk you through the key concepts of RTK. We'll also cover how to use &lt;code&gt;createEntityAdapter&lt;/code&gt; for optimized data handling and demonstrate how to dispatch actions and select state in a React app, all while keeping the code clean and minimal. 🚀&lt;/p&gt;

&lt;p&gt;We'll follow this project structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;📂 src
├── 📄 store.js
├── 📄 todoSlice.js
├── 📄 App.jsx
├── 📂 components
├────── 📂 TodoList
├───────── 📄 index.jsx
├───────── 📄 styles.css
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Chek the this &lt;a href="https://github.com/dionarodrigues/labs/tree/master/simple-todo-rkt" rel="noopener noreferrer"&gt;repo with all the files&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Install Dependencies
&lt;/h3&gt;

&lt;p&gt;First, install the necessary dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @reduxjs/toolkit react-redux
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Setting Up the Redux Store
&lt;/h3&gt;

&lt;p&gt;Before we create the reducers, we need to set up our Redux store using &lt;code&gt;configureStore&lt;/code&gt; from Redux Toolkit. Here, we define a &lt;code&gt;todos&lt;/code&gt; slice in the store, which will be managed by &lt;code&gt;todoReducer&lt;/code&gt;. This reducer will be created in the next step to handle actions like adding, toggling, and removing to-dos. Additionally, the slice name (todos) will be visible in the Redux DevTools, making it easy to track state changes during development.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// store.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;configureStore&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@reduxjs/toolkit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;todoReducer&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./todoSlice&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;configureStore&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;reducer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;todoReducer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Creating the To-Do Slice (Reducers &amp;amp; Actions)
&lt;/h3&gt;

&lt;p&gt;In this step, we'll define the to-do slice using &lt;code&gt;createSlice&lt;/code&gt;, which generates reducers and actions for managing our to-do list. We'll start with a simple array-based approach, where each to-do item is stored as an object with &lt;code&gt;id&lt;/code&gt;, &lt;code&gt;text&lt;/code&gt;, and &lt;code&gt;completed&lt;/code&gt; properties. The reducers will handle adding, toggling, and removing to-dos.&lt;/p&gt;

&lt;p&gt;Later, we'll improve this implementation by using &lt;code&gt;createEntityAdapter&lt;/code&gt;, which helps structure the state more efficiently by normalizing the data and generating optimized selectors and reducers. For now, we'll keep things simple and manage the list manually.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// todoSlice.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createSlice&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@reduxjs/toolkit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Initial state is an empty array, which will hold the to-do items&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;initialState&lt;/span&gt; &lt;span class="o"&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;todoSlice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createSlice&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="c1"&gt;// The name of the slice that will appear in the Redux DevTools&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;todos&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="c1"&gt;// The initial state of the slice&lt;/span&gt;
  &lt;span class="nx"&gt;initialState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="c1"&gt;// Reducers define how the state is updated based on dispatched actions&lt;/span&gt;
  &lt;span class="na"&gt;reducers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Adds a new to-do to the list with a unique id, text, and a completed status (defaulted to false)&lt;/span&gt;
    &lt;span class="na"&gt;addTodo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&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;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="c1"&gt;// Use the current timestamp as a unique id&lt;/span&gt;
        &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// The text for the new to-do item&lt;/span&gt;
        &lt;span class="na"&gt;completed&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;// New to-dos are not completed by default&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;

    &lt;span class="c1"&gt;// Toggles the completed status of a to-do item when it's clicked&lt;/span&gt;
    &lt;span class="na"&gt;toggleTodo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&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;todo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;todo&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;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Find the to-do by its id&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;completed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;completed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Toggle the completed status&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;

    &lt;span class="c1"&gt;// Removes a to-do item from the list by its id&lt;/span&gt;
    &lt;span class="na"&gt;removeTodo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&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;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;todo&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;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Filter out the to-do to be removed&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Export the actions generated by createSlice&lt;/span&gt;
&lt;span class="k"&gt;export&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;addTodo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;toggleTodo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;removeTodo&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;todoSlice&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Selector to get all to-dos from the store state&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;selectTodos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Export the reducer function, which will be used in the store setup&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;todoSlice&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reducer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Building the To-Do List UI
&lt;/h3&gt;

&lt;p&gt;In this step, we’ll create the user interface (UI) for our to-do list application using React. The UI will allow users to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add new to-dos by typing into an input field and clicking the "Add" button.&lt;/li&gt;
&lt;li&gt;Toggle the completion status of a to-do by clicking on the task itself, which will mark it as completed or incomplete.&lt;/li&gt;
&lt;li&gt;Remove to-dos by clicking the delete (❌) button next to each item.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We'll use React hooks like &lt;code&gt;useState&lt;/code&gt; for local state and &lt;code&gt;useDispatch&lt;/code&gt; and &lt;code&gt;useSelector&lt;/code&gt; from &lt;code&gt;react-redux&lt;/code&gt; to interact with the Redux store. The UI will display a list of to-dos, and we'll conditionally apply styles to indicate whether a task is completed or not. The layout will be simple, and you can &lt;a href="https://github.com/dionarodrigues/labs/blob/master/simple-todo-rkt/src/components/TodoList/styles.css" rel="noopener noreferrer"&gt;check the basic styling here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let’s get started by building the TodoList component!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useSelector&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useDispatch&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-redux&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;addTodo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;toggleTodo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;removeTodo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;selectTodos&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../../todoSlice&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./styles.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Import the CSS file&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;TodoList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setInput&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&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;// Local state for the input field&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useDispatch&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Dispatch to trigger Redux actions&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;todos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selectTodos&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Select todos from the Redux store&lt;/span&gt;

  &lt;span class="c1"&gt;// Handle adding a new todo&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleAddTodo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Check if input is not just whitespace&lt;/span&gt;
      &lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;addTodo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt; &lt;span class="c1"&gt;// Dispatch addTodo action&lt;/span&gt;
      &lt;span class="nf"&gt;setInput&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;// Reset input field after adding the todo&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="c1"&gt;// Handle toggling the completion status of a todo&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleToggleTodo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;toggleTodo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// Dispatch toggleTodo action to mark as completed or not&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;todo-container&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;todo-title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;To&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;Do&lt;/span&gt; &lt;span class="nx"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Input field and Add button */&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;input-container&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;
          &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="o"&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="nf"&gt;setInput&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="c1"&gt;// Update input state on change&lt;/span&gt;
          &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;todo-input&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="nx"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Add a new task...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleAddTodo&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;add-button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="nx"&gt;Add&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* List of todos */&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ul&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;todo-list&lt;/span&gt;&lt;span class="dl"&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;todos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;todo&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;li&lt;/span&gt;
            &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`todo-item &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;completed&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;completed&lt;/span&gt;&lt;span class="dl"&gt;'&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="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// Add 'completed' class if the task is completed&lt;/span&gt;
          &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Checkbox to mark a task as completed or not */&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;flex&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;alignItems&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;center&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;
                &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;checkbox&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                &lt;span class="nx"&gt;checked&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;completed&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// Checkbox checked state based on todo's completed status&lt;/span&gt;
                &lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="o"&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="nf"&gt;handleToggleTodo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt; &lt;span class="c1"&gt;// Handle checkbox toggle&lt;/span&gt;
                &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;todo-checkbox&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
              &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
              &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;span&lt;/span&gt;
                &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;
                  &lt;span class="na"&gt;textDecoration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;completed&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;line-through&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;none&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="c1"&gt;// Strike-through text if completed&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;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
              &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/span&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/label&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Remove button to delete a todo */&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt;
              &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&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="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;removeTodo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;))}&lt;/span&gt; &lt;span class="c1"&gt;// Dispatch removeTodo action&lt;/span&gt;
              &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;remove-button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
            &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="err"&gt;❌&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/li&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="p"&gt;))}&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ul&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;TodoList&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Adicional explanations:
&lt;/h4&gt;

&lt;p&gt;By using &lt;code&gt;useSelector&lt;/code&gt;, the component automatically subscribes to the Redux store and re-renders whenever the state it depends on (the list of &lt;code&gt;todos&lt;/code&gt;) changes. Similarly, &lt;code&gt;useDispatch&lt;/code&gt; provides the function needed to send actions to update the state in the store.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;selectTodos&lt;/code&gt; function is a selector that returns the list of todos from the store, which is then used to display the tasks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using &lt;code&gt;createEntityAdapter&lt;/code&gt; for efficient state management
&lt;/h2&gt;

&lt;p&gt;When managing collections of data in Redux, handling updates, deletions, and retrievals efficiently can become complex. Redux Toolkit’s &lt;code&gt;createEntityAdapter&lt;/code&gt; simplifies this process by normalizing data and providing optimized selectors and reducers out of the box.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Use &lt;code&gt;createEntityAdapter&lt;/code&gt;?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Normalized State&lt;/strong&gt; – Stores data in an object with IDs as keys instead of an array, making lookups and updates more efficient.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prebuilt Reducers&lt;/strong&gt; – Includes &lt;code&gt;addOne&lt;/code&gt;, &lt;code&gt;addMany&lt;/code&gt;, &lt;code&gt;removeOne&lt;/code&gt;, &lt;code&gt;updateOne&lt;/code&gt;, and more, reducing boilerplate code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auto-Generated Selectors&lt;/strong&gt; – Provides optimized selectors (&lt;code&gt;selectAll&lt;/code&gt;, &lt;code&gt;selectById&lt;/code&gt;, etc.) to retrieve entities easily.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Enhancing &lt;code&gt;todoSlice.js&lt;/code&gt; with &lt;code&gt;createEntityAdapter&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Now, we'll see how to improve the &lt;code&gt;todoSlice.js&lt;/code&gt; we previously created by using &lt;code&gt;createEntityAdapter&lt;/code&gt;. This approach will make our Redux state management more efficient, reducing boilerplate code and improving performance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createSlice&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;createEntityAdapter&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@reduxjs/toolkit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Create an adapter for the to-do list&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;todosAdapter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createEntityAdapter&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Define the initial state using the adapter's getInitialState&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;initialState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;todosAdapter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getInitialState&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Create the slice&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;todoSlice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createSlice&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;todos&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// The slice name will appear in Redux DevTools&lt;/span&gt;
  &lt;span class="nx"&gt;initialState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;reducers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Adds a new to-do using the adapter's addOne function&lt;/span&gt;
    &lt;span class="na"&gt;addTodo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&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;todosAdapter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addOne&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="c1"&gt;// Generate a unique ID based on timestamp&lt;/span&gt;
        &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// The text of the to-do&lt;/span&gt;
        &lt;span class="na"&gt;completed&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;// Default to not completed&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;

    &lt;span class="c1"&gt;// Toggles the completion status of a to-do item&lt;/span&gt;
    &lt;span class="na"&gt;toggleTodo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&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;todo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;entities&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// Access by ID&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;completed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;completed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Toggle completed status&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;

    &lt;span class="c1"&gt;// Removes a to-do using the adapter's removeOne function&lt;/span&gt;
    &lt;span class="na"&gt;removeTodo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&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;todosAdapter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeOne&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Export actions&lt;/span&gt;
&lt;span class="k"&gt;export&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;addTodo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;toggleTodo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;removeTodo&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;todoSlice&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Generate selectors using the adapter&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;selectAll&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;selectTodos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;selectById&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;selectTodoById&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="nx"&gt;todosAdapter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSelectors&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Export the reducer for the store setup&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;todoSlice&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reducer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Redux slice data without Adapter:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;todos&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="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Buy groceries&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;completed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Finish project&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;completed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Call mom&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;completed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;todos&lt;/code&gt; array stores objects, making it necessary to iterate over the array to find or modify items. To find a specific &lt;code&gt;todo&lt;/code&gt;, we need to use &lt;code&gt;.find()&lt;/code&gt; or &lt;code&gt;.filter()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Updates require manually mapping through the array and modifying the correct item.&lt;/p&gt;

&lt;h4&gt;
  
  
  Redux slice data with Adapter:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;ids&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;// Stores the order of IDs&lt;/span&gt;
    &lt;span class="na"&gt;entities&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Buy groceries&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;completed&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="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Finish project&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;completed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Call mom&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;completed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Cleaner Code: Removes redundant logic.&lt;/li&gt;
&lt;li&gt;Better Performance: Direct lookups instead of filtering through an array.&lt;/li&gt;
&lt;li&gt;Easier Maintenance: Uses built-in Redux Toolkit methods.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Key Differences &amp;amp; Benefits of &lt;code&gt;createEntityAdapter&lt;/code&gt;
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Without &lt;code&gt;createEntityAdapter&lt;/code&gt;
&lt;/th&gt;
&lt;th&gt;With &lt;code&gt;createEntityAdapter&lt;/code&gt;
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;State Structure&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Array of objects&lt;/td&gt;
&lt;td&gt;Normalized with &lt;code&gt;entities&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Lookup Efficiency&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;O(n)&lt;/code&gt; (Loop through array)&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;O(1)&lt;/code&gt; (Direct access via &lt;code&gt;entities&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Adding a Todo&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;push&lt;/code&gt; new object&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;addOne&lt;/code&gt; method&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Toggling Todo&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Find by &lt;code&gt;id&lt;/code&gt; then update&lt;/td&gt;
&lt;td&gt;Directly modify &lt;code&gt;entities[id]&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Removing Todo&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Filter out by &lt;code&gt;id&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;removeOne&lt;/code&gt; method&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Selectors&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Manually written&lt;/td&gt;
&lt;td&gt;Auto-generated (&lt;code&gt;selectAll&lt;/code&gt;, &lt;code&gt;selectById&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://redux-toolkit.js.org/" rel="noopener noreferrer"&gt;Redux Toolkit Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://redux.js.org/" rel="noopener noreferrer"&gt;Redux docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=5yEG6GhoJBs&amp;amp;t=2034s&amp;amp;ab_channel=CosdenSolutions" rel="noopener noreferrer"&gt;RTK tutorial on youtube&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Redux Toolkit has transformed state management by simplifying Redux development and reducing boilerplate. With powerful utilities like &lt;code&gt;configureStore&lt;/code&gt;, &lt;code&gt;createSlice&lt;/code&gt;, and &lt;code&gt;createEntityAdapter&lt;/code&gt;, RTK enforces best practices while making state handling more efficient.&lt;/p&gt;

&lt;p&gt;In this article, we explored the core concepts of Redux Toolkit and built a to-do list to demonstrate its benefits. We also compared manual state management with &lt;code&gt;createEntityAdapter&lt;/code&gt;, highlighting how it normalizes data, improves performance, and simplifies CRUD operations.&lt;/p&gt;

&lt;p&gt;By adopting Redux Toolkit, developers can write cleaner, more maintainable Redux code with minimal setup. If you're still managing state the old way, now is the perfect time to embrace RTK for a better development experience! 😃&lt;/p&gt;

&lt;p&gt;See you in the next article!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>react</category>
      <category>redux</category>
    </item>
    <item>
      <title>NVM Basics &amp; Bash Aliases: Simplify Your Development Workflow</title>
      <dc:creator>Diona Rodrigues</dc:creator>
      <pubDate>Mon, 24 Feb 2025 21:07:58 +0000</pubDate>
      <link>https://forem.com/dionarodrigues/nvm-basics-bash-aliases-simplify-your-development-workflow-202g</link>
      <guid>https://forem.com/dionarodrigues/nvm-basics-bash-aliases-simplify-your-development-workflow-202g</guid>
      <description>&lt;p&gt;&lt;strong&gt;As developers, managing different versions of Node.js and streamlining terminal commands are essential for productivity. Tools like Node Version Manager (NVM) and Bash Aliases can make a big difference, especially when working on multiple projects with different dependencies, like varying Node or React versions.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this article, we’ll explore how NVM helps you manage Node.js versions for different projects and how Bash Aliases can simplify repetitive commands, making your development workflow faster and more efficient. Let’s dive in!&lt;/p&gt;

&lt;h2&gt;
  
  
  NVM (Node Version Manager)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/nvm-sh/nvm" rel="noopener noreferrer"&gt;NVM (Node Version Manager)&lt;/a&gt; is a crucial tool for managing multiple versions of &lt;a href="https://nodejs.org/en" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt;, especially when working on projects that require different Node or React versions&lt;/strong&gt;. For instance, if one project needs an older React version while another uses a newer one, NVM lets you easily switch between versions to maintain compatibility without interfering with other projects. This flexibility ensures that each project runs with the right version of Node.js, eliminating version conflicts and improving your workflow.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to install NVM
&lt;/h3&gt;

&lt;p&gt;You can install NVM first using a script or package manager (like curl or wget). Open your terminal and run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-o-&lt;/span&gt; https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will download and install NVM. After installation, close and reopen your terminal.&lt;/p&gt;

&lt;h3&gt;
  
  
  Install Node.js via NVM
&lt;/h3&gt;

&lt;p&gt;After installing NVM, you can use it to install different versions of Node.js with commands like &lt;code&gt;nvm install &amp;lt;version&amp;gt;&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nvm &lt;span class="nb"&gt;install &lt;/span&gt;22
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Basic NVM commands
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Use a specific Node.js Version
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nvm use 22
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  List all installed Node.js versions
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nvm &lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Set a default Node.js version:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nvm &lt;span class="nb"&gt;alias &lt;/span&gt;default 22
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With these commands, you can manage and switch between different versions of Node.js for various projects. Learn more in the &lt;a href="https://github.com/nvm-sh/nvm" rel="noopener noreferrer"&gt;NVM Github repository&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bash Aliases
&lt;/h2&gt;

&lt;p&gt;Bash Aliases are shorthand commands that allow you to simplify long or complex commands. By creating aliases, you can save time and effort when running frequently used commands, whether it's for navigating to project directories or executing npm scripts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating Bash Aliases
&lt;/h3&gt;

&lt;p&gt;To create custom aliases, you'll need to modify your Bash configuration file. Here's how to do it:&lt;/p&gt;

&lt;h4&gt;
  
  
  Edit the Bash Configuration File
&lt;/h4&gt;

&lt;p&gt;Open your &lt;code&gt;~/.bashrc&lt;/code&gt; file using your preferred text editor (we’ll use nano here):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nano ~/.bashrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Add Aliases
&lt;/h4&gt;

&lt;p&gt;In the &lt;code&gt;.bashrc&lt;/code&gt; file, add the following alias syntax to define your custom commands.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;alias&lt;/span&gt; &amp;lt;alias_name&amp;gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;command&amp;gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's an example of Bash aliases that you can use to switch between different Node versions for different React project paths.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# React Project 1 (Requires Node 16.x)&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;react_project_1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"cd ~/Documents/develop/project-1 &amp;amp;&amp;amp; nvm use 16 &amp;amp;&amp;amp; npm start"&lt;/span&gt;

&lt;span class="c"&gt;# React Project 2 (Requires Node 20.x)&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;react_project_2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"cd ~/Documents/develop/project-2 &amp;amp;&amp;amp; nvm use 20 &amp;amp;&amp;amp; npm start"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, the aliases above, mean:&lt;/p&gt;

&lt;p&gt;Change the current directory to the project folder, switch to Node.js version 16 (or 20, depending on the alias), and start the React development server.&lt;/p&gt;

&lt;h4&gt;
  
  
  Reload the Bash File
&lt;/h4&gt;

&lt;p&gt;To activate the aliases, after saving the file, you'll need to reload the &lt;code&gt;.bashrc&lt;/code&gt; file by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;source&lt;/span&gt; ~/.bashrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Using the Bash aliases
&lt;/h4&gt;

&lt;p&gt;Use the aliases just like a regular command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;react_project_1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;By utilizing NVM and Bash Aliases, you can significantly simplify your development workflow. NVM allows you to manage different versions of Node.js for various projects, while Bash Aliases save you time by turning long commands into easy-to-remember shortcuts.&lt;/p&gt;

&lt;p&gt;Together, these tools can help you focus more on development and less on managing environments or repeatedly typing out long commands.&lt;/p&gt;

&lt;h3&gt;
  
  
  For further reading, check out these helpful resources:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://linuxize.com/post/how-to-create-bash-aliases/" rel="noopener noreferrer"&gt;How to Create Bash Aliases (Linuxize)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/oyetoket/how-to-create-productive-bash-command-aliases-practical-guide-2d23"&gt;Creating Productive Bash Command Aliases (Dev.to)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nvm-sh/nvm" rel="noopener noreferrer"&gt;NVM GitHub Repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.freecodecamp.org/news/node-version-manager-nvm-install-guide/" rel="noopener noreferrer"&gt;freeCodeCamp's NVM Install Guide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By implementing these tools, you'll be able to optimize your development environment and work more efficiently. Happy coding! 😊&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>workflow</category>
      <category>node</category>
      <category>bash</category>
    </item>
    <item>
      <title>From useEffect to React Query: Modernizing your data management in react</title>
      <dc:creator>Diona Rodrigues</dc:creator>
      <pubDate>Mon, 18 Nov 2024 13:16:58 +0000</pubDate>
      <link>https://forem.com/dionarodrigues/from-useeffect-to-react-query-modernizing-your-data-management-in-react-1a6a</link>
      <guid>https://forem.com/dionarodrigues/from-useeffect-to-react-query-modernizing-your-data-management-in-react-1a6a</guid>
      <description>&lt;p&gt;&lt;strong&gt;In the modern web development landscape, building fast, responsive applications that efficiently manage server-side data is more crucial than ever. Traditional methods of fetching data in React, especially using &lt;code&gt;useEffect&lt;/code&gt;, can often lead to complex state management, repetitive code, and performance issues. With &lt;a href="https://tanstack.com/query/latest" rel="noopener noreferrer"&gt;React Query&lt;/a&gt;, developers can take advantage of features like automatic caching, background fetching, and built-in mutation support, all while minimising boilerplate code.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this article, we'll explore the core concepts of &lt;a href="https://tanstack.com/query/latest" rel="noopener noreferrer"&gt;React Query&lt;/a&gt;, demonstrate how to integrate it into our projects, and highlight its powerful features that can significantly improve your development workflow. Get ready to transform the way you fetch, cache, and synchronise data in your React applications!&lt;/p&gt;

&lt;h2&gt;
  
  
  Why should we stop fetching data using React Effects
&lt;/h2&gt;

&lt;p&gt;While using React's &lt;code&gt;useEffect&lt;/code&gt; for data fetching is perfectly valid, there are several reasons to consider moving away from it in favor of a dedicated data fetching library like React Query (even the &lt;a href="https://react.dev/reference/react/useEffect#what-are-good-alternatives-to-data-fetching-in-effects" rel="noopener noreferrer"&gt;React documentation suggests using React Query for data fetching&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  Some downsides of using Effects for data fetching:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Performance Issues&lt;/strong&gt;: “network waterfalls” and unnecessary re-fetching are some of the common issues when using React &lt;code&gt;useEffect&lt;/code&gt; and can lead to a very bad user experience.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lack of Built-in Caching&lt;/strong&gt;: &lt;code&gt;useEffect&lt;/code&gt; does not provide caching out of the box, which causes repeated network requests and complex solutions to manage it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complexity in State Management&lt;/strong&gt;: managing loading, error, and data states manually with &lt;code&gt;useEffect&lt;/code&gt; can lead to cumbersome and error-prone code, especially as the application scales.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Effects don’t run on server&lt;/strong&gt;: data will may not be available when the component initially renders.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How React Query works
&lt;/h2&gt;

&lt;p&gt;React Query is a powerful library designed to simplify data fetching and state management in React applications. Here’s a breakdown of how React Query works:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Querying Data
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;useQuery&lt;/code&gt; hook&lt;/strong&gt;: The core of React Query is the &lt;code&gt;useQuery&lt;/code&gt; hook. This hook allows you to fetch data from a server and automatically manage its state (loading, error, data…).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Query key&lt;/strong&gt;: Each query is identified by a unique key (one or more strings in an array). This key helps React Query cache and manage the data efficiently.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Caching
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Automatic caching&lt;/strong&gt;: When data is fetched, React Query caches it. If the same query is made again, it retrieves data from the cache instead of making a new network request.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stale data management&lt;/strong&gt;: You can define how long data should be considered fresh (not stale). After this period, React Query will refetch the data in the background.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Background Refetching
&lt;/h3&gt;

&lt;p&gt;React Query automatically refetches data in several scenarios to keep the data fresh and in sync. Here are the main situations when this happens:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Mounting of components&lt;/strong&gt;: When a component mounts, if the data is considered stale.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Window focus&lt;/strong&gt;: Whenever the window regains focus, such as when a user switches between tabs or windows and returns to the one containing your application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Network reconnection&lt;/strong&gt;: If the network connection is lost and later restored.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Data Mutations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;useMutation Hook: it refers to the process of creating, updating, or deleting data on the server. Unlike querying, which retrieves data, &lt;code&gt;useMutation&lt;/code&gt; is used to modify data and manage side effects associated with it.&lt;/li&gt;
&lt;li&gt;Optimistic updates: when a user performs an action that will mutate data, the UI is updated right away to reflect the anticipated outcome of that action, enhancing user experience.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. Query Invalidation
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;React Query allows you to mark a cached query as "stale" so that it will be refetched the next time it's accessed. This is essential for ensuring that the UI reflects the most up-to-date data from the server after certain actions, such as mutations or user interactions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  6. Automatic Garbage Collection
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;React Query automatically removes queries from its cache when they are no longer being used and have been inactive for a certain period&lt;/strong&gt;. This process helps prevent memory leaks and ensures that only relevant data stays in the cache.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  7. DevTools
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;React Query DevTools is an optional, user-friendly tool for React Query that helps us, developers, debug and monitor queries, mutations, and cache state&lt;/strong&gt;. It provides a visual interface to inspect the details of our queries and see how React Query manages their lifecycle.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  8. Server-Side Rendering (SSR)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;React Query supports Server-Side Rendering (SSR), which helps in pre-fetching data on the server before sending it to the client. This makes initial page loads faster and can improve SEO by serving a fully rendered page to search engines.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to implement React Query
&lt;/h2&gt;

&lt;p&gt;Here’s a step-by-step guide on how to use React Query to manage server data fetching, caching, updating, and synchronization in a React app.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Install React Query
&lt;/h3&gt;

&lt;p&gt;First, add React Query to your project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;npm&lt;/span&gt; &lt;span class="nx"&gt;install&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;tanstack&lt;/span&gt;&lt;span class="sr"&gt;/react-quer&lt;/span&gt;&lt;span class="err"&gt;y
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Setup &lt;code&gt;QueryClientProvider&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;To configure React Query, wrap your app in a &lt;code&gt;QueryClientProvider&lt;/code&gt;. This provider uses a &lt;code&gt;QueryClient&lt;/code&gt; instance, which manages caching, background fetching, and updates.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;QueryClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;QueryClientProvider&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@tanstack/react-query&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;queryClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;QueryClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;QueryClientProvider&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;queryClient&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;YourComponent&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/QueryClientProvider&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Fetch Data with &lt;code&gt;useQuery&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;useQuery&lt;/code&gt; hook fetches data from an API, automatically caching it and handling states like loading and errors.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useQuery&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@tanstack/react-query&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;YourComponent&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;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isLoading&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useQuery&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;todos&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;fetchTodos&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Loading&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&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;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;todo&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;))}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Sample fetch function&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchTodos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &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;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/todos&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="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&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;ul&gt;
&lt;li&gt;Key &lt;code&gt;(['todos'])&lt;/code&gt;: Each &lt;code&gt;useQuery&lt;/code&gt; requires a unique key to identify and cache data.&lt;/li&gt;
&lt;li&gt;Query Function (&lt;code&gt;fetchTodos&lt;/code&gt;): This async function fetches the data you need from an API.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 4: Handle Data Mutations with &lt;code&gt;useMutation&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;useMutation&lt;/code&gt; hook is used to create, update, or delete data. Once a mutation is successful, you can use query invalidation to refetch relevant data and keep your app’s state up to date.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useMutation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useQueryClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@tanstack/react-query&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;TodoAdder&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;queryClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useQueryClient&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;addTodoMutation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useMutation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;addTodo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;onSuccess&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;queryClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;invalidateQueries&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;todos&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="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&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;addTodoMutation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mutate&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;New Todo&lt;/span&gt;&lt;span class="dl"&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;Add&lt;/span&gt; &lt;span class="nx"&gt;Todo&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;addTodo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newTodo&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;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/todos&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="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&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="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newTodo&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&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;ul&gt;
&lt;li&gt;Mutation Function (&lt;code&gt;addTodo&lt;/code&gt;): This async function modifies the server state.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;onSuccess&lt;/code&gt;: After a mutation, this callback invalidates the &lt;code&gt;['todos']&lt;/code&gt; query, refetching and updating the data to show the newly added todo.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 5: Optional DevTools for Debugging
&lt;/h3&gt;

&lt;p&gt;React Query DevTools can help you monitor queries, cache status, and more during development:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;npm&lt;/span&gt; &lt;span class="nx"&gt;install&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;tanstack&lt;/span&gt;&lt;span class="sr"&gt;/react-query-devtool&lt;/span&gt;&lt;span class="err"&gt;s
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, add &lt;code&gt;&amp;lt;ReactQueryDevtools /&amp;gt;&lt;/code&gt; to your app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ReactQueryDevtools&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@tanstack/react-query-devtools&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;QueryClientProvider&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;queryClient&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;YourComponent&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ReactQueryDevtools&lt;/span&gt; &lt;span class="nx"&gt;initialIsOpen&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/QueryClientProvider&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Replacing &lt;code&gt;useEffect&lt;/code&gt; with &lt;a href="https://tanstack.com/query/latest" rel="noopener noreferrer"&gt;React Query for data fetching&lt;/a&gt; and side effects is a great recommendation for building modern React applications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;React Query transforms the way you handle server-side data in React apps, providing a more declarative approach that simplifies complex state management. By leveraging its powerful features like caching, background synchronization, and query invalidation, you can create highly responsive and performant applications&lt;/strong&gt;. And last, but not least, integrating React Query DevTools makes it easy to monitor and debug, ensuring that your app’s data flow is smooth and transparent.&lt;/p&gt;

&lt;p&gt;Whether you’re building a simple single-page app or a complex data-heavy application, React Query empowers you to build faster, smarter, and more user-friendly apps with less effort.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>react</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Web accessibility, how to design web pages for everyone</title>
      <dc:creator>Diona Rodrigues</dc:creator>
      <pubDate>Sun, 09 Jun 2024 15:18:43 +0000</pubDate>
      <link>https://forem.com/dionarodrigues/web-accessibility-how-to-design-web-pages-for-everyone-4k75</link>
      <guid>https://forem.com/dionarodrigues/web-accessibility-how-to-design-web-pages-for-everyone-4k75</guid>
      <description>&lt;p&gt;&lt;strong&gt;As developers, how can we make at least the web more accessible for all? That’s the main question of this article and here we’ll explore some ideas to make our websites more inclusive, a place where people with disabilities can also use the internet to learn something new, acquire some different skill, buy products and many other actions that most of us do in our daily digital life and maybe have never thought about it before.&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Accessibility: It’s About People” - &lt;a href="https://www.w3.org/WAI/people/" rel="noopener noreferrer"&gt;W3C&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Did you know that &lt;strong&gt;1.3 billion people (16% of the world’s population) are estimated to live with some form of disability nowadays&lt;/strong&gt; and that they face many issues related not only with stigma and discrimination, but also exclusion from education and employment? Information from the &lt;a href="https://www.who.int/news-room/fact-sheets/detail/disability-and-health" rel="noopener noreferrer"&gt;World Health Organization (WHO) report on disability&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is accessibility when it comes to web
&lt;/h2&gt;

&lt;p&gt;In short, &lt;strong&gt;web accessibility, more specifically, is about diversity, equity and inclusion&lt;/strong&gt;: everyone can perceive, understand, navigate and interact with the web no matter what their ability or circumstances.&lt;/p&gt;

&lt;p&gt;Some examples of disabilities that affect access to the web are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Visual&lt;/strong&gt;: includes people with blindness, low-level vision, and color blindness. Following WHO reports, &lt;a href="https://www.who.int/en/news-room/fact-sheets/detail/blindness-and-visual-impairment" rel="noopener noreferrer"&gt;2.2 billion people in the world have a near or distance vision impairment&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auditory&lt;/strong&gt;: deaf and hard-of-hearing (DHH) people. The WHO states that &lt;a href="https://www.who.int/en/news-room/fact-sheets/detail/deafness-and-hearing-loss" rel="noopener noreferrer"&gt;5% of the world's population needs rehabilitation to deal with their disabling hearing loss&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cognitive&lt;/strong&gt;: refers to a broad range of disabilities that include intellectual disability, dyslexia, autism, brain injury, stroke, Alzheimer's disease…&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Speech&lt;/strong&gt;: difficulty in a person's ability to produce sounds that create words.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mobility&lt;/strong&gt;: difficulty performing movements ranging from walking to manipulating objects with your hands.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is important to note that &lt;strong&gt;some disabilities are permanent, but many of them are also temporary&lt;/strong&gt;, such as not being able to use your smartphone with your hands while driving, so voice command solutions can be useful here, for example; or cannot hear sound at the moment, then subtitles in videos can help the user to better understand the content.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Web accessibility is about creating web content, design, and tools that can be used by everyone regardless of ability.” - &lt;a href="https://monsido.com/web-accessibility" rel="noopener noreferrer"&gt;Monsido&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  How to improve user experience with web accessibility
&lt;/h2&gt;

&lt;p&gt;Accessibility standards, in addition to &lt;a href="https://www.w3.org/WAI/standards-guidelines/wcag/" rel="noopener noreferrer"&gt;WCAG (Web Content Accessibility Guidelines provided by W3C)&lt;/a&gt;, also involve &lt;a href="https://www.w3.org/WAI/policies/" rel="noopener noreferrer"&gt;local/country laws and policies&lt;/a&gt;, as well as the type of product and industry, and a combination of all of them will definitely lead to digital design being more accessible for everyone.&lt;/p&gt;

&lt;p&gt;In this article, we will focus on some well-known web accessibility principles for improving user experience on web pages and most of them are certainly included in your country's government requirements as well.&lt;/p&gt;

&lt;h3&gt;
  
  
  Semantic HTML
&lt;/h3&gt;

&lt;p&gt;The most basic principle of web accessibility is also a bit generic, but here it's important for you to know that &lt;strong&gt;you should use HTML tags correctly to help &lt;a href="https://en.wikipedia.org/wiki/Screen_reader" rel="noopener noreferrer"&gt;screen readers&lt;/a&gt;&lt;/strong&gt; understand and navigate the content, identifying titles, subtitles and paragraphs, for example.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set the language of the document by using the &lt;code&gt;lang&lt;/code&gt; attribute in the opening &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; tag.&lt;/li&gt;
&lt;li&gt;Replace &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; tags to semantic HTML elements, such as &lt;code&gt;&amp;lt;main&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;article&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;section&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;header&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;nav&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;footer&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Be sure to use heading tags to achieve logical levels of content structure, not because you want to only display larger font sizes: &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;h2&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;h3&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;h4&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;h5&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;h6&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Nest HTML elements correctly, otherwise browsers and &lt;a href="https://www.w3.org/WAI/people-use-web/tools-techniques/#at" rel="noopener noreferrer"&gt;assistive technologies&lt;/a&gt; may not be able to understand the content as intended.&lt;/li&gt;
&lt;li&gt;Use lists whenever you need to display a list of items, like a menu or ingredients on a receipt, for example: &lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;ol&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Use&lt;code&gt;&amp;lt;table&amp;gt;&lt;/code&gt; only when you need to display structured tabular data, not for layout or anything else.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Read more about &lt;a href="https://developer.mozilla.org/en-US/curriculum/core/semantic-html/" rel="noopener noreferrer"&gt;semantic HTML in this MDN article&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Document Title
&lt;/h3&gt;

&lt;p&gt;One of the main HTML tags, &lt;strong&gt;&lt;code&gt;&amp;lt;title&amp;gt;&lt;/code&gt; (the document title element located in the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt;) is the first piece of information that screen readers say when users navigate between pages&lt;/strong&gt;. This is also important because it appears in the browser tab, helping the user to know where they are and navigate between the pages open in their browser.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Title should be unique for every page of your site and any other related site;&lt;/li&gt;
&lt;li&gt;It should be a descriptive phrase related to the content of the page.&lt;/li&gt;
&lt;li&gt;If the title is long, try to put the most important words in the first 55-60 characters, as search engines usually display around that.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Read more on &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/title" rel="noopener noreferrer"&gt;Page Title in MDN&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Alt Text (Image Alternative Text)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Images, which are part of the content and not just decorative, must have alternative texts to describe them&lt;/strong&gt;, so that blind people (or those with low vision) and screen readers can understand them. Users who disable images to save bandwidth also take advantage of this feature.&lt;/p&gt;

&lt;p&gt;Alt text are included by the "alt" attribute in the &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; HTML tag, see example bellow:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;img src=“logo.png” alt=“Diona Rodrigues logo” /&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It’s important to use short, concise and appropriate alternative texts for images:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Alt text must always be associated with the image content.&lt;/li&gt;
&lt;li&gt;If the image is just decorative, leave the "alt" attribute blank.&lt;/li&gt;
&lt;li&gt;For functional images, such as images used as buttons, they should start with action words like “submit” and “go to”, for example.&lt;/li&gt;
&lt;li&gt;If there is text in the image, such as a logo, for example, this text must be in the alternative text.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Read more about &lt;a href="https://web.dev/learn/accessibility/images" rel="noopener noreferrer"&gt;alt text on web.dev&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keyboard navigation and focus
&lt;/h3&gt;

&lt;p&gt;Although some users, for several reasons, prefer to &lt;strong&gt;navigate a web page using only the keyboard&lt;/strong&gt;, people with low vision or blindness can use the keyboard combined with a screen reader for this purpose and browsers by default have a visual style to be applied to the elements receiving focus.&lt;/p&gt;

&lt;p&gt;You can play around with this by going to this &lt;a href="https://mdn.github.io/learning-area/tools-testing/cross-browser-testing/accessibility/native-keyboard-accessibility.html" rel="noopener noreferrer"&gt;MDN project to see how native keyboard accessibility works&lt;/a&gt; by pressing the tab key.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Normally the navigation order by pressing the tab key depends on the HTML structure, however you can change it using the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex" rel="noopener noreferrer"&gt;HTML attribute called “tabindex”&lt;/a&gt;. This attribute receives numbers, where the number 0 (tabindex="0") means that the element follows the natural order as it appears in the DOM; Negative numbers cause elements to be removed from the natural order of focus. Then, the priority focus order will be based on positive numbers, where the smallest has higher priority over the largest (1, 2, 3...).&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Learn/Accessibility/HTML#skip_links" rel="noopener noreferrer"&gt;Skip links&lt;/a&gt; are very useful for allowing users to skip the header and navigate to the main content of a page. They are usually visually hidden and can be accessed by pressing "tab" key. It is normally the first element that will receive focus on a page.&lt;/li&gt;
&lt;li&gt;Although we can disable styling for focused HTML elements, you should never do this. However, you can create your own style like the example below.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;See how to change the style of a focused HTML element by changing the outline CSS property:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nd"&gt;:focus&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;outline&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="n"&gt;hsla&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;220&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;80%&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;Alternatively, you can replace the outline CSS property with the box-shadow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nd"&gt;:focus&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;outline&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;box-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;3px&lt;/span&gt; &lt;span class="n"&gt;hsla&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;220&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;80%&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;Read more about &lt;a href="https://web.dev/learn/accessibility/focus" rel="noopener noreferrer"&gt;keyboard navigation and focus on web.dev&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Color and contrast
&lt;/h3&gt;

&lt;p&gt;Following the &lt;a href="https://www.w3.org/WAI/WCAG22/Understanding/intro#understanding-the-four-principles-of-accessibility" rel="noopener noreferrer"&gt;WCAG Four Accessibility Principles&lt;/a&gt;, &lt;strong&gt;all users must be able to perceive the content on the page, and therefore color and contrast are vital to achieving this&lt;/strong&gt;. Color should not be used as the sole visual means of conveying information, indicating an action, or distinguishing a visual element, as color may not be seen by colour-deficient users. And the contrast between the text and the background should be enough for users with moderately low vision to read it.&lt;/p&gt;

&lt;p&gt;To measure contrast, WCAG uses a technique called “contrast ratio,” which takes the difference in luminance (or brightness) between the colours of foreground and background content (i.e., usually text) and checks its legibility. I really recommend you read &lt;a href="https://webaim.org/articles/contrast/" rel="noopener noreferrer"&gt;“Contrast and Color Accessibility” by WebAIM&lt;/a&gt; to understand more about it.&lt;/p&gt;

&lt;p&gt;Check out a list of suggestions to make content more accessible with color and contrast:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;WCAG defines some types of text as “incidental,” meaning they have no contrast requirements: inactive elements (such as disabled buttons), decorative elements (such as text in images used only for background decoration purposes), invisible elements (like a &lt;a href="https://developer.mozilla.org/en-US/docs/Learn/Accessibility/HTML#skip_links" rel="noopener noreferrer"&gt;skip link&lt;/a&gt;) and part of an image that contains other significant visual content (like a license plate in an image showing city traffic, for example).&lt;/li&gt;
&lt;li&gt;Make sure the contrast between text (and also images of text) and background has a contrast ratio of at least 4.5:1. Larger text (minimum size of 18pt, or 14 pt bold) should have a ratio of at least 3:1. You can use tools like &lt;a href="https://webaim.org/resources/contrastchecker/" rel="noopener noreferrer"&gt;Contrast Checker&lt;/a&gt; to measure it.&lt;/li&gt;
&lt;li&gt;Avoid high color contrast scheme for your site as it can make reading difficult for people with dyslexia, as &lt;a href="https://www.w3.org/WAI/RD/2012/text-customization/r11" rel="noopener noreferrer"&gt;this study&lt;/a&gt; shows.&lt;/li&gt;
&lt;li&gt;Don’t rely solely on colours to convey information, as some people will not be able to see these colours. So, instead of using red colour to mark required form fields, mark them with an asterisk and in red, for example.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Read more about &lt;a href="https://webaim.org/articles/contrast/" rel="noopener noreferrer"&gt;color and contrast in this WebAIM article&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Typography and Text Resizing
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Typography plays a big role on web pages and it is essential to choose the correct font family, font size, as well as properties such as letter and line spacing to make texts readable. Additionally, some users with low vision may need to zoom in to read content better, so relative rather than absolute sizes are very important for web accessibility.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Some tips for better typography when it comes to web accessibility:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Studies show that &lt;a href="http://dyslexiahelp.umich.edu/sites/default/files/good_fonts_for_dyslexia_study.pdf" rel="noopener noreferrer"&gt;people with disabilities find it easier to read texts using common fonts&lt;/a&gt; such as Helvetica, Arial and Times New Roman, for example. Therefore, avoid choosing fonts with cursive designs or artistic shapes.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://webaim.org/techniques/fonts/#limited" rel="noopener noreferrer"&gt;Avoid using too many different typefaces&lt;/a&gt;, as this can make our brain have more effort and spend more time to build a map of their characters and patterns to parse words when reading a text.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://webaim.org/techniques/textlayout/#line" rel="noopener noreferrer"&gt;Line length should be between 50 and 120 characters&lt;/a&gt; to provide comfort when returning to the beginning of the next line.&lt;/li&gt;
&lt;li&gt;Font sizes should be based on relative values ​​(%, rem or em) to easily be resized when needed (using browser zoom for example).&lt;/li&gt;
&lt;li&gt;Since screen readers cannot read text embedded in images, use markup texts.&lt;/li&gt;
&lt;li&gt;Mainly for long texts, use elements such as headings, subheadings, lists and quotes, for example, to break the linearity of the content and make reading more comfortable.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.w3.org/WAI/WCAG21/Understanding/text-spacing" rel="noopener noreferrer"&gt;WCAG defines how text spacing should be applied&lt;/a&gt;, with some exceptions, and shows that the spacing between letters must be at least 0.12 times the font size; line height/spacing, 1.5 times; spacing between paragraphs, 2 times; and spacing between words, 0.16 times. Be careful because short and large spaces can also affect readability.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Read more about &lt;a href="https://web.dev/learn/accessibility/typography" rel="noopener noreferrer"&gt;typography in web.dev&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  More web accessibility improvements
&lt;/h3&gt;

&lt;p&gt;Above you saw many aspects of a web page that you can improve, providing a better experience for all users, especially those with permanent or temporary disabilities. And of course there are other elements that you can also take into consideration, like ARIA, forms, animation, video and audio, for example. So I strongly suggest you take a look at &lt;a href="https://web.dev/learn/accessibility" rel="noopener noreferrer"&gt;web.dev&lt;/a&gt; and &lt;a href="https://developer.mozilla.org/en-US/docs/Learn/Accessibility" rel="noopener noreferrer"&gt;MDN documentation&lt;/a&gt; to learn more about it.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to mesure web accessibility
&lt;/h2&gt;

&lt;p&gt;The sooner accessibility is assessed the better, so if you are starting a new project I suggest you plan to apply at least the web accessibility best practices I mentioned in the previous section. Otherwise, it's best to group the improvements you need to apply and find the best way to do so based on the specifics of your existing project.&lt;/p&gt;

&lt;p&gt;There are many ways to mesure web accessibility, from checklists to online tools and browser extensions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.w3.org/WAI/test-evaluate/tools/list/" rel="noopener noreferrer"&gt;Web Accessibility Evaluation Tools List by W3C&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.a11yproject.com/checklist/" rel="noopener noreferrer"&gt;Web Accessibility Checklist by A11Y Project&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.w3.org/WAI/test-evaluate/preliminary/" rel="noopener noreferrer"&gt;WC3 Web Accessibility Checklist&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://accessibility.huit.harvard.edu/auto-tools-testing" rel="noopener noreferrer"&gt;Automated Tools for Testing Accessibility by Harvard University&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Resources for learning about web accessibility
&lt;/h2&gt;

&lt;p&gt;There are many ways to build a successful accessible website, and a good start is to follow the &lt;a href="https://www.w3.org/WAI/standards-guidelines/wcag/" rel="noopener noreferrer"&gt;international Web Content Accessibility Guidelines (WCAG)&lt;/a&gt; created and maintained by the W3C. Because they are an extensive documentation, you can firstly learn &lt;a href="https://www.w3.org/WAI/standards-guidelines/wcag/glance/" rel="noopener noreferrer"&gt;WCAG 2 at a Glance&lt;/a&gt;, that combine different grouped guidelines.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Learn/Accessibility" rel="noopener noreferrer"&gt;Mozilla's MDN&lt;/a&gt; is another great resource for learning about web accessibility and is sure to provide all the knowledge you need to improve websites and applications, making them accessible to everyone.&lt;/p&gt;

&lt;p&gt;The Google team, through &lt;a href="https://web.dev/learn/accessibility" rel="noopener noreferrer"&gt;web.dev&lt;/a&gt;, also offers an easy-to-understand course on web accessibility, where you will find several examples and practical suggestions on how to apply them.&lt;/p&gt;

&lt;p&gt;Utah University also has a great project called &lt;a href="https://webaim.org/articles/" rel="noopener noreferrer"&gt;WebAIM&lt;/a&gt; full of articles to learn about web accessibility.&lt;/p&gt;

&lt;p&gt;At least but not least, I found a website called &lt;a href="https://monsido.com/web-accessibility" rel="noopener noreferrer"&gt;Monsido&lt;/a&gt;, which also has good explanations on the subject.&lt;/p&gt;

&lt;h2&gt;
  
  
  References on web cccessibility
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.who.int/news-room/fact-sheets/detail/disability-and-health" rel="noopener noreferrer"&gt;Disability by World Health Organisation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.w3.org/WAI/fundamentals/" rel="noopener noreferrer"&gt;Accessibility Fundamentals Overview by W3C&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Learn/Accessibility/What_is_accessibility" rel="noopener noreferrer"&gt;What is accessibility? by MDN&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://monsido.com/web-accessibility" rel="noopener noreferrer"&gt;Introduction to Web Acessibility by Monsido&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://web.dev/learn/accessibility" rel="noopener noreferrer"&gt;Learn Accessibility by web.dev&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.w3.org/WAI/fundamentals/accessibility-principles/" rel="noopener noreferrer"&gt;Accessibility Principles&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Videos on Youtube
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=pj4lVJIjRZ0&amp;amp;ab_channel=Webflow" rel="noopener noreferrer"&gt;Enhancing visual design with web accessibility by WebFlow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=hE83Qn-PTGA&amp;amp;ab_channel=NNgroup" rel="noopener noreferrer"&gt;Accessibility vs. Inclusive Design by NNGroup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=QWPWgaDqbZI&amp;amp;ab_channel=TED" rel="noopener noreferrer"&gt;The Internet's Accessibility Problem — and How To Fix It by Clive Loseby on TED&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=zoAFBJl9DHQ&amp;amp;ab_channel=HubSpotMarketing" rel="noopener noreferrer"&gt;Web Accessibility: ADA Compliance Tips to Design for All Users (FREE Checklist!) by HubSpot Marketing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=TomOQYxFnrU&amp;amp;ab_channel=ChromeforDevelopers" rel="noopener noreferrer"&gt;Accessibility - The State of the Web by Chrome for Developers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Web accessibility is how to create websites for everyone and should not be an option, on the contrary, it is non-negotiable when it comes to web pages.&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Accessibility is essential for developers and organisations that want to create high-quality websites and web tools, and not exclude people from using their products and services.” - &lt;a href="https://www.w3.org/WAI/fundamentals/accessibility-intro/" rel="noopener noreferrer"&gt;W3C&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There are several types of disabilities such as low vision, blindness, depth, autism, dyslexia, difficulty producing sound, and many others, and all of them must be taken into consideration when developing a web page, and certainly the set of strategies for Improving web accessibility will also depend on the type of project, industry and government laws.&lt;/p&gt;

&lt;p&gt;By following at least some of the suggestions I left in this article, your web project will certainly provide a much better user experience for everyone in different contexts. Also, I really recommend that you take a look at all the links I've added throughout this article as they provide more information that can guide you through this process.&lt;/p&gt;

&lt;p&gt;See you next time! 😁&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>webacessibility</category>
      <category>webdev</category>
      <category>inclusion</category>
    </item>
    <item>
      <title>6 useful CSS features you might not know about</title>
      <dc:creator>Diona Rodrigues</dc:creator>
      <pubDate>Sat, 27 Apr 2024 17:20:25 +0000</pubDate>
      <link>https://forem.com/dionarodrigues/6-useful-css-features-you-might-not-know-about-4cjg</link>
      <guid>https://forem.com/dionarodrigues/6-useful-css-features-you-might-not-know-about-4cjg</guid>
      <description>&lt;p&gt;&lt;strong&gt;CSS is getting bigger and bigger and even though we work daily with this style language, we do not know all the features we can use to better help us in our daily development. But in this article I will show you some CSS properties that can make a difference in your code. 😁&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Some time ago I created an article called &lt;a href="https://dev.to/dionarodrigues/6-powerful-css-techniques-you-can-use-instead-of-javascript-2f44"&gt;6 Powerful CSS Techniques You Can Use Instead of Javascript&lt;/a&gt; and now I decided to extend this list by adding 6 other good CSS features that I believe can be useful and that most of us may not know about them.&lt;/p&gt;

&lt;h2&gt;
  
  
  ::marker
&lt;/h2&gt;

&lt;p&gt;I won't judge you if you still use &lt;code&gt;list-style-type&lt;/code&gt; or &lt;code&gt;::before&lt;/code&gt; to change the marker of a list element, don't worry. 😁 However, I would like to introduce you to the CSS pseudo-element called &lt;code&gt;::marker&lt;/code&gt;. This feature was released a few years ago and is supported in all modern browsers and provides everything we need to customize not only the bullet content, but also the color, white space and all animations, transitions and font properties.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="nd"&gt;::marker&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;content&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="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.2em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;purple&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;Keep in mind that this pseudo-element has greater specificity than &lt;code&gt;list-style-type&lt;/code&gt;. Read more about the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/::marker" rel="noopener noreferrer"&gt;CSS ::marker pseudo-element in the MDN documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  currentcolor
&lt;/h2&gt;

&lt;p&gt;What if you want the border color of an element to be the same as the text color? Assuming you have a &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; whose border and the text inside it are blue, how would you manage it? I bet you probably thought about setting the same color twice, once for the property called “text” and once for the “border-color”, right? Forget it because now you can use the &lt;code&gt;currentcolor&lt;/code&gt; keyword as it refers to the value of the “color” property.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;blue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="n"&gt;currentcolor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* border-color will be blue */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Read more about this old &lt;a href="https://www.w3schools.com/colors/colors_currentcolor.asp" rel="noopener noreferrer"&gt;currentcolor keyword in w3schools&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  color-mix()
&lt;/h2&gt;

&lt;p&gt;For me, this is one of the coolest fully supported CSS features introduced in 2022 but started working in all modern browsers last year. I can't imagine how powerful this can be when we need to create a color palette by mixing two different colours - something that was only possible to do automatically using a JavaScript-based solution.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.result&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;color-mix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="n"&gt;srgb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;blue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;red&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhc9jronqcwzrhgoag2km.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhc9jronqcwzrhgoag2km.jpg" alt="CSS color-mix function" width="800" height="612"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first parameter of this &lt;code&gt;color-mix()&lt;/code&gt; function is a bit strange but it refers to the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/color-interpolation-method" rel="noopener noreferrer"&gt;interpolation method&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Read more about color-mix() in this fantastic &lt;a href="https://www.smashingmagazine.com/2022/06/simplify-color-palette-css-color-mix/" rel="noopener noreferrer"&gt;article by Smashing Magazine&lt;/a&gt;. And also in this another &lt;a href="https://developer.mozilla.org/en-US/blog/color-palettes-css-color-mix/" rel="noopener noreferrer"&gt;article on by MDN&lt;/a&gt;. And &lt;a href="https://codepen.io/smashingmag/pen/jOZvVqM" rel="noopener noreferrer"&gt;play around with this Codepen example&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  mix-blend-mode
&lt;/h2&gt;

&lt;p&gt;Have you ever played around with blending modes in some graphics software, like Photoshop, to merge colours and patterns between background and foreground to create cool images? Now CSS also provides a way to do this effect by using the property &lt;code&gt;mix-blend-mode&lt;/code&gt;. Among many effects, you can use “multiply”, for example, which results in the multiplication of the top and bottom colours.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.img&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;mix-blend-mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;multiply&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo7eb5b35vye2smh6uiht.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo7eb5b35vye2smh6uiht.jpg" alt="CSS mix-blend-mode property" width="800" height="612"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Read more about &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/backdrop-filter" rel="noopener noreferrer"&gt;mix-blend-mode and all possible effects in the MDN documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  backdrop-filter
&lt;/h2&gt;

&lt;p&gt;Released about 7 years after CSS Filters, the CSS &lt;code&gt;backdrop-filter&lt;/code&gt; property allows us to apply graphic effects to the area behind the element. Just like the previous CSS property, it can be very useful when you want to make the interface more visually appealing.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Because it applies to everything behind the element, to see the effect the element or its background needs to be transparent or partially transparent. - &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/backdrop-filter" rel="noopener noreferrer"&gt;MDN docs&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.title&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;rgb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;255&lt;/span&gt; &lt;span class="m"&gt;255&lt;/span&gt; &lt;span class="m"&gt;255&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="m"&gt;30%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;backdrop-filter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;grayscale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;75%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F21ei2p2wwlkyi0jqlpi8.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F21ei2p2wwlkyi0jqlpi8.jpg" alt="CSS backdrop-filter property" width="800" height="612"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Read more about &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" rel="noopener noreferrer"&gt;backdrop-filter and all possible effects in the MDN documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  accent-color
&lt;/h2&gt;

&lt;p&gt;Last but not least, if you, like me, worked with CSS before 2022, you know how difficult it was to change the colours of checkbox and radio inputs, right? Although we still have a limitation to manage this type of HTML controls, we now have a CSS property called &lt;code&gt;accent-color&lt;/code&gt; to easily manage their colours in some state.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;'checkbox'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;accent-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;purple&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above styles can be seen when a checkbox is checked. Read more about &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/accent-color" rel="noopener noreferrer"&gt;accent-color in the MDN documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;CSS has been greatly improved and many new features appear every year and some that we don't know about have been around for a long time. The secret is not to try to memorize them all, but once you know them it becomes easier to understand what you can do using just CSS, which can greatly improve performance - in addition to the fact that it can be much easier to maintain the code.&lt;/p&gt;

&lt;p&gt;I hope you learned something here and that this article has inspired you to continue searching for CSS features.&lt;/p&gt;

&lt;p&gt;See you next time! 😁&lt;/p&gt;

</description>
      <category>css</category>
      <category>webdev</category>
      <category>ui</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Docker compose, orchestrating and automating services</title>
      <dc:creator>Diona Rodrigues</dc:creator>
      <pubDate>Sun, 21 Apr 2024 14:36:35 +0000</pubDate>
      <link>https://forem.com/dionarodrigues/docker-compose-orchestrating-and-automating-services-3ajg</link>
      <guid>https://forem.com/dionarodrigues/docker-compose-orchestrating-and-automating-services-3ajg</guid>
      <description>&lt;p&gt;&lt;strong&gt;Docker compose is a tool that allows us to replace most of the commands and configurations that we normally run in the terminal to orchestrate and automate Docker services: such as creating several containers based on different images, connected to each other by networks and using volumes to persist their data, for example.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Even working on a simple dockerized project, we often run several different Docker commands in the terminal. And this entire process must be memorized following a specific order to execute the same commands as many times as necessary during the development life cycle. I think you can imagine how complicated it can be especially on large projects, right?&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s Docker compose?
&lt;/h2&gt;

&lt;p&gt;If you are the kind of developer who saves Docker commands in a text file along with other instructions that you need to memorize, I would like to introduce Docker compose to you. :)&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Compose simplifies the control of your entire application stack, making it easy to manage services, networks, and volumes in a single, comprehensible YAML configuration file. Then, with a single command, you create and start all the services from your configuration file.” - &lt;a href="https://docs.docker.com/compose/" rel="noopener noreferrer"&gt;Docker documentation&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Docker commands to be converted into Docker compose
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;In the next section you will find a Docker compose file example containing commands to create 3 different containers used in a same application: "database" container using Mongo, "backend" using Node and "frontend" using React.&lt;/strong&gt; The database container will be based on a Docker hub image, while the backend and frontend will have specific directories in the local project with their own custom images and files. The database and backend containers must be connected as we need to run CRUD methods on the database and we do this using Docker networking. In addition to these settings, we will also have other settings such as ports to provide a way to make requests to the backend from the frontend, and volumes and bind mounts to persist data.&lt;/p&gt;

&lt;p&gt;Let's imagine the following basic directories and files structure&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├── backend/
│ ├── Dockerfile
│ └── app.js
├── env/
│ ├── backend.env
│ └── mongo.env
├── frontend/
│ ├── Dockerfile
│ └── src
├── compose.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can check out all the Docker commands from the above scenario - and their full explanations -(which we could run in the terminal, but which will be translated into configurations in Docker compose file) in two articles I wrote before called &lt;a href="https://dev.to/dionarodrigues/how-to-use-docker-images-containers-volumes-and-bind-mounts-295b"&gt;How to use Docker Images, Containers, Volumes and Bind Mounts&lt;/a&gt; and &lt;a href="https://dev.to/dionarodrigues/docker-networking-how-to-connect-different-containers-364d"&gt;How to connect different containers with Docker networking&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a Docker compose file
&lt;/h2&gt;

&lt;p&gt;Now it’s time to create the compose file based on the scenario described in the previous section.&lt;/p&gt;

&lt;h3&gt;
  
  
  Docker compose file
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;First of all, create a file in the root project directories called &lt;code&gt;compose.yaml&lt;/code&gt;&lt;/strong&gt;. &lt;a href="https://yaml.org/" rel="noopener noreferrer"&gt;YAML is a text format&lt;/a&gt; that uses indentation to specify dependencies between configuration options. Be aware that incorrect indentation will cause problems with executing commands properly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;mongodb&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;mongo'&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;data:/data/db&lt;/span&gt;
    &lt;span class="na"&gt;env_file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./env/mongo.env&lt;/span&gt;
  &lt;span class="na"&gt;backend&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./backend&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;80:80'&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./backend:/app&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/app/node_modules&lt;/span&gt;
    &lt;span class="na"&gt;env_file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./env/backend.env&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;mongodb&lt;/span&gt;
  &lt;span class="na"&gt;frontend&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./frontend&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3000:3000'&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./frontend/src:/app/src&lt;/span&gt;
    &lt;span class="na"&gt;stdin_open&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;tty&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;backend&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Docker compose file explanations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;services&lt;/strong&gt;: we can understand Docker service as a container. Therefore, this top-level element called &lt;a href="https://docs.docker.com/compose/compose-file/05-services/" rel="noopener noreferrer"&gt;“services” is a key map where each key represents an individual container&lt;/a&gt;, which will be created following its configurations: such as image, volumes and ports, for example. So here we see three different containers named "mongodb", "frontend" and "backend".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;image&lt;/strong&gt;: this key specifies the image this container is based on to be created. It can be a local image or an image from the &lt;a href="https://hub.docker.com/" rel="noopener noreferrer"&gt;Docker hub&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;build&lt;/strong&gt;: is used to define the &lt;code&gt;dockerfile&lt;/code&gt; path to build an image to be used by this service. It's useful when the image isn't already created.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;volumes&lt;/strong&gt; (inside services): when inside the service, specifies the volumes this container will create (or use if already created).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;volumes&lt;/strong&gt; (same level of services): At the top level, this key specifies all &lt;a href="https://docs.docker.com/compose/compose-file/07-volumes/" rel="noopener noreferrer"&gt;named volumes created in each service that should be shared among all services&lt;/a&gt;. Each named volume must be on a line followed by a comma. This syntax is a little strange because there is nothing after the comma, but this is how it should be declared.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;env_file&lt;/strong&gt;: defines the path of a file containing the environment variables to be used by the service.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;depends_on&lt;/strong&gt;: when working with multiple containers, it is used to specify when a container depends on another container to run. In the above example, the frontend container will be created only after the backend which will be created after mongodb.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ports&lt;/strong&gt;: &lt;a href="https://docs.docker.com/network/#published-ports" rel="noopener noreferrer"&gt;exposes a container port to a port on the host machine&lt;/a&gt; (&lt;code&gt;local_port:container_port&lt;/code&gt;). In our case, the backend can be accessed with port 80 while the frontend with port 3000 (&lt;code&gt;localhost:80&lt;/code&gt; and &lt;code&gt;localhost:3000&lt;/code&gt; respectively).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;stdin_open&lt;/strong&gt; and &lt;strong&gt;tty&lt;/strong&gt;: &lt;a href="https://docs.docker.com/reference/cli/docker/container/run/#interactive" rel="noopener noreferrer"&gt;allow we send input to the Docker container&lt;/a&gt;, which is important when working with React, for example.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Some important extra notes:
&lt;/h4&gt;

&lt;p&gt;We can also create a key called &lt;code&gt;networks&lt;/code&gt; inside each service to connect all containers which have the same network names. However, as Docker already do it automatically, most of the times it's not necessary. Like volumes, &lt;a href="https://docs.docker.com/compose/compose-file/06-networks/" rel="noopener noreferrer"&gt;networks must be declared at the top-level to be shared across different services&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you want to declare &lt;a href="https://docs.docker.com/compose/environment-variables/set-environment-variables/#use-the-environment-attribute" rel="noopener noreferrer"&gt;environment vars within this compose file&lt;/a&gt;, you can use the &lt;code&gt;environment&lt;/code&gt; key instead of &lt;code&gt;env_file&lt;/code&gt;. Be aware that if you need to prevent others from seeing this sensitive data you should use a file and add this file in &lt;code&gt;.gitignore&lt;/code&gt;, for example.&lt;/p&gt;

&lt;p&gt;The services keys are the container names. So you can use these names to create connection between containers. For example, you can connect to the mongodb container from the backend using a solution like &lt;code&gt;mongodb://mongodb:27017/my_database_name&lt;/code&gt; where the second "mongodb" is the name of the mongodb container.&lt;/p&gt;

&lt;p&gt;While we need to specify the absolute system path to use bind mounts to map our project's folders and files with those inside the Docker container when running the command in the terminal, in the docker compose file we only need the relative path.&lt;/p&gt;

&lt;h4&gt;
  
  
  Commands to run and manage Docker compose
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;docker compose --help&lt;/code&gt;: see all options you can use with &lt;code&gt;docker compose&lt;/code&gt; command&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;docker compose up&lt;/code&gt;: to build, create and start all images and containers&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;docker compose up -d&lt;/code&gt;: same as above but run containers in detach mode (in background)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;docker compose down&lt;/code&gt;: stops and removes containers and networks created by up&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;docker compose down -v&lt;/code&gt;: same as above but also delete volumes&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;docker compose down -v -rmi&lt;/code&gt;: same as above but also delete images used by services&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Check &lt;a href="https://docs.docker.com/compose/reference/#command-options-overview-and-help" rel="noopener noreferrer"&gt;all docker compose CLI options&lt;/a&gt; in the Docker docs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Docker compose helps to quickly set up a development environment for our dockerized projects, especially when using multiple containers. And once this file is created and our services are configured correctly within this file, we can start the containers by running just one command in the terminal.&lt;/p&gt;

&lt;p&gt;I also showed how to orchestrate containers so that one starts exactly when another is already created, and also how to configure ports and manage volumes using Docker Compose.&lt;/p&gt;

&lt;p&gt;I hope you learned a lot from this article.&lt;br&gt;
See you next time! 😁&lt;/p&gt;

</description>
      <category>docker</category>
      <category>webdev</category>
      <category>devops</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Docker networking, how to connect different containers</title>
      <dc:creator>Diona Rodrigues</dc:creator>
      <pubDate>Thu, 11 Apr 2024 21:34:43 +0000</pubDate>
      <link>https://forem.com/dionarodrigues/docker-networking-how-to-connect-different-containers-364d</link>
      <guid>https://forem.com/dionarodrigues/docker-networking-how-to-connect-different-containers-364d</guid>
      <description>&lt;p&gt;&lt;strong&gt;Having different containers is quite common when using Docker in a project, such as one for the React application, one for the backend, and one for the database, for example. And in this article I will show you how to connect these different containers using a solution called container &lt;br&gt;
networking.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Following Docker best practices, each container should have only one responsibility, that’s why we usually have different containers in a project. But how can all these containers be connected and communicate with each other or use services outside the Docker? The answer for this question is a feature called networking.&lt;/p&gt;
&lt;h2&gt;
  
  
  Scenario overview
&lt;/h2&gt;

&lt;p&gt;All examples in this article will be based on the following example: a Node JS application that needs to create, read, update and delete data (CRUD) from a Mongo database (but can be applied to any type of language and services as the main idea here is to demonstrate how we can have different but connected containers).&lt;/p&gt;

&lt;p&gt;So, &lt;strong&gt;let's imagine we have a Node JS file that has methods for managing data from a Mongo database. In this file we also need to connect to the database to be able to execute all these methods.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this scenario we will have two containers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a container to run the Node JS application (which contains all the methods mentioned above and also the connection to the database)&lt;/li&gt;
&lt;li&gt;another container to run Mongo db&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Next, we will focus on connecting to the Mongo database as this is the most important part of this article.&lt;/p&gt;
&lt;h2&gt;
  
  
  Connecting different containers using network
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;“You can create custom, user-defined networks, and connect multiple containers to the same network. Once connected to a user-defined network, containers can communicate with each other using container IP addresses or container names.” - &lt;a href="https://docs.docker.com/network/#user-defined-networks" rel="noopener noreferrer"&gt;Docker docs&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At this point you should know how to run containers via command line. I have an article called &lt;a href="https://dionarodrigues.dev/blog/how-to-use-docker-images-containers-volumes-and-bind-mounts" rel="noopener noreferrer"&gt;“How to use Docker Images, Containers and Volumes”&lt;/a&gt; where you can learn about it in details.&lt;/p&gt;
&lt;h3&gt;
  
  
  1- Creating networks
&lt;/h3&gt;

&lt;p&gt;The first step is to create a network to connect the containers.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;docker network create [network_name]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;docker network create my_app_net&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  2- Running Mongo db container connected to the created network
&lt;/h3&gt;

&lt;p&gt;Now it’s time to run the Mongo db container via command line and connect it to the network.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;docker run -d --network my_app_net --name mongo_db mongo&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Where &lt;code&gt;my_app_net&lt;/code&gt; is the network created above, &lt;code&gt;mongo_database&lt;/code&gt; is the name of this container, and &lt;code&gt;mongo&lt;/code&gt; is the name of the image this container is based on. The container name is important because we will use it in the next step.&lt;/p&gt;
&lt;h3&gt;
  
  
  3- Connecting to Mongo db container from Node JS file
&lt;/h3&gt;

&lt;p&gt;As I mentioned in the Scenario Overview section, let's imagine here that we have a Node JS file that needs to connect to the Mongo database container created in the previous step. Then we can have the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;mongoose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mongodb://mongo_db:27017/my_database_name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="err"&gt;…&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Where &lt;code&gt;mongo_db&lt;/code&gt; is the name of the container created in the previous step and &lt;code&gt;27017&lt;/code&gt; is just the port provided by Mongo (you can read more about this in its &lt;a href="https://www.mongodb.com/docs/manual/reference/default-mongodb-port/" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;). In a non-Docker solution, when we install Mongo on our host machine, &lt;code&gt;mongo_db&lt;/code&gt; would be &lt;code&gt;localhost&lt;/code&gt; or an IP address - in this case, it is the name of the container that contains the database we want to connect to.&lt;/p&gt;

&lt;h3&gt;
  
  
  4- Running Node JS container connected to the Mongo db container
&lt;/h3&gt;

&lt;p&gt;Once we have the Mongo db container running - and the database connection in the Node JS file is already configured to connect to this container - all we need to do now is start this Node JS container using the same network as the Mongo container uses.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;docker run -d --rm  -p 3000:3000 --network my_app_net --name my_app my_node_img&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Where &lt;code&gt;my_app_net&lt;/code&gt; is the above created network, &lt;code&gt;my_app&lt;/code&gt; is the name of this container and &lt;code&gt;my_node_img&lt;/code&gt; is the name of the image which this container is based on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;And that’s all. Now you know how to connect containers using Docker container networking.&lt;/strong&gt; :)&lt;/p&gt;

&lt;p&gt;You can read more about &lt;a href="https://docs.docker.com/network/" rel="noopener noreferrer"&gt;networking in the Docker documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Connecting containers to services installed on our host machine
&lt;/h2&gt;

&lt;p&gt;When we want to connect to a service installed on our host machine from a Docker container, we have a different way of doing it.&lt;/p&gt;

&lt;p&gt;Now, &lt;strong&gt;let's imagine we have a Mongo database installed on our host machine instead of a container. When started, this service exposes a port that can be accessed using: &lt;code&gt;//localhost:27017/my_database_name&lt;/code&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In order to have this url working fine inside the container, and be able to execute CRUD on the db, we should replace &lt;code&gt;localhost&lt;/code&gt; to &lt;code&gt;host.docker.internal&lt;/code&gt;. This special domain will be understood by Docker and be translated to the IP address of our host machine as seen inside Docker container. So it will be something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;mongoose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mongodb://host.docker.internal:27017/my_database_name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Read more about this &lt;a href="https://docs.docker.com/desktop/networking/#i-want-to-connect-from-a-container-to-a-service-on-the-host" rel="noopener noreferrer"&gt;special Docker DNS name here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;As we learned, communication between containers is easier to implement using the Docker network, so all we need to do is create a network and use it to run all the containers that must be connected.&lt;/p&gt;

&lt;p&gt;We also saw that we can also use special Docker DNS names to connect services outside of Docker from our containers.&lt;/p&gt;

&lt;p&gt;I hope you liked it.&lt;br&gt;
See you next time! 😁&lt;/p&gt;

</description>
      <category>docker</category>
      <category>webdev</category>
      <category>devops</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to use Docker Images, Containers, Volumes and Bind Mounts</title>
      <dc:creator>Diona Rodrigues</dc:creator>
      <pubDate>Sat, 30 Mar 2024 23:53:16 +0000</pubDate>
      <link>https://forem.com/dionarodrigues/how-to-use-docker-images-containers-volumes-and-bind-mounts-295b</link>
      <guid>https://forem.com/dionarodrigues/how-to-use-docker-images-containers-volumes-and-bind-mounts-295b</guid>
      <description>&lt;p&gt;&lt;strong&gt;Even if you already work with Docker and want to better understand its core concepts or are trying to learn how this open source platform works, this article can help you dive into Docker images, containers, volumes, and bind mounts providing not only explanations of what are, but also how to use them.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Docker is a tool for managing containers and containers, in a nutshell, are packages containing everything a software needs to run, such as system tools, libraries and code. Using Docker, we can quickly deploy and scale applications across multiple environments, ensuring they run the same way even on different machines.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“A container is an isolated environment for your code.” - &lt;a href="https://docs.docker.com/guides/walkthroughs/what-is-a-container/" rel="noopener noreferrer"&gt;Docker documentation&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In Node JS projects, for example, the Node version as well as the dependencies used in the project will always have the same versions on the team's machines, as well as on production versus staging versus local machines. Another advantage is that we don't need to install Node on our local machine and all project dependencies every time we run the project, they will be managed by Docker through images, containers, volumes and bind mounts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Docker Images, Containers, Volumes and Bind Mounts
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Images&lt;/strong&gt;: templates / blueprints of code to be executed in a Docker container.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Containers&lt;/strong&gt;: they are instances of Docker images, which means they are responsible for running and executing code. Different containers can be created based on the same image, but each of them will have its own data and state.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Volumes&lt;/strong&gt;: the mechanism for persisting data outside of containers, fully managed by Docker using a dedicated directory on our host machine.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bind Mounts&lt;/strong&gt;: is another way to make data stored on our host machine accessible by containers. By using this option we manually bind a file or directory on the host machine to be mounted into a container.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Images can be shared and reused by different containers while containers are created and destroyed over an application’s lifecycle.&lt;/p&gt;

&lt;p&gt;Once an image is built, it creates a snapshot of the code and lock it. So, in case we need to update the code inside a container a new image should be created to be used by the containers attached to it. Of course there are other ways to make it flexible using volumes and bind mounts.&lt;/p&gt;

&lt;p&gt;Last but not least, data can be managed using volumes and bind mounts, and there are different ways to do this, but I will explain later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Docker commands reference
&lt;/h2&gt;

&lt;p&gt;This is a brief reference to some commands that you will see in the next sections.&lt;/p&gt;

&lt;h3&gt;
  
  
  Main commands
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;docker build [path_of_the_dockerfile]&lt;/code&gt; (or just . (dot) if it’s running from the same directory): creates an image based on dockerfile instructions&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;docker run -p [local_port]:[image_exposed_port] [imge_id/name]&lt;/code&gt;: creates a container based on the image and enable a local port to access the project&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;docker —help&lt;/code&gt;: we can use it along with any docker command to see a list of related commands and their explanations&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Docker image commands
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;docker images&lt;/code&gt;: list all images&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;docker rmi [image_id/name]&lt;/code&gt;: delete the image&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;docker image prune&lt;/code&gt;: delete all unused images&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;docker image prune -a&lt;/code&gt;: delete all images&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;docker inspect [image_id/name]&lt;/code&gt;: display info about the image&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Docker container commands
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;docker ps&lt;/code&gt;: shows all containers that are running&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;docker ps -a&lt;/code&gt;: shows all created containers&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;docker stop [container_id/name]&lt;/code&gt;: stops the container&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;docker start [container_id/name]&lt;/code&gt;: starts an existing container&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;docker logs [container_id/name]&lt;/code&gt;: display all the logs of that container in the terminal&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;docker rm [container_id/name]&lt;/code&gt;: delete the container&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Docker volume commands
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;docker volume ls&lt;/code&gt;: lists all volumes&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;docker volume rm [volume_name]&lt;/code&gt;: deletes volume&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;docker volume prune&lt;/code&gt;: removes all unused volumes&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What's Dockerfile
&lt;/h2&gt;

&lt;p&gt;Dockerfile is the name of the file - usually created in the root project directory - to handle the instructions to create an image for our project (we can also specify other images we are going to use to compose our own image, like Node image, as well as some instructions to copy files, install dependencies…).&lt;/p&gt;

&lt;p&gt;As you see, images can be shared and the main tool to manage it is the &lt;a href="https://hub.docker.com/" rel="noopener noreferrer"&gt;Docker hub&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example of Dockerfile
&lt;/h3&gt;

&lt;p&gt;Note: The code below is based on a Node application and will be used through this article as an example for most of the commands in the next sections.&lt;/p&gt;

&lt;p&gt;Let's imagine that we have an application containing a file called &lt;code&gt;server.js&lt;/code&gt; that is responsible for this Node application and exposes it on port 80.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Build this image based on node image&lt;/span&gt;
&lt;span class="nx"&gt;FROM&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;
&lt;span class="c1"&gt;// The working directory (it is created if it doesn't already exist and because of it)&lt;/span&gt;
&lt;span class="nx"&gt;WORKDIR&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;
&lt;span class="c1"&gt;// Copy package.json into /app folder&lt;/span&gt;
&lt;span class="nx"&gt;COPY&lt;/span&gt; &lt;span class="kr"&gt;package&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;
&lt;span class="c1"&gt;// Install all dependencies&lt;/span&gt;
&lt;span class="nx"&gt;RUN&lt;/span&gt; &lt;span class="nx"&gt;npm&lt;/span&gt; &lt;span class="nx"&gt;install&lt;/span&gt;
&lt;span class="c1"&gt;// Copy all directories and files from the root into /app folder&lt;/span&gt;
&lt;span class="nx"&gt;COPY&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="c1"&gt;// Expose the Node application port&lt;/span&gt;
&lt;span class="nx"&gt;EXPOSE&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;
&lt;span class="c1"&gt;// Run default commands when a container is started&lt;/span&gt;
&lt;span class="nx"&gt;CMD&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;server.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://docs.docker.com/reference/dockerfile/#:~:text=A%20Dockerfile%20is%20a%20text,can%20use%20in%20a%20Dockerfile." rel="noopener noreferrer"&gt;See all supported instructions by Dockerfile&lt;/a&gt; in the Docker documentation.&lt;/p&gt;

&lt;p&gt;Difference between &lt;code&gt;RUN&lt;/code&gt; and &lt;code&gt;CMD&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;RUN&lt;/code&gt; executes the instruction when the &lt;strong&gt;image&lt;/strong&gt; is created&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CMD&lt;/code&gt; executes the instruction when the &lt;strong&gt;container&lt;/strong&gt; is started&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Docker image layers
&lt;/h2&gt;

&lt;p&gt;When an image is rebuilt, Docker is smart enough to recognise what have been changed and then use the cached result of the instructions instead execute every instruction again and again, which is great for optimisation. It’s called layer based architecture, where each instruction represents a layer that is cached.&lt;/p&gt;

&lt;p&gt;Once a layer is changed (i.e. the result of an instruction), Docker runs that layer and the next ones again instead of getting them from the cache, which is why we first copy &lt;code&gt;package.json&lt;/code&gt; and install its dependencies in the example above before copying all other files. By doing this, we guarantee that dependencies will only be reinstalled when &lt;code&gt;package.json&lt;/code&gt; is changed. If we add &lt;code&gt;package.json&lt;/code&gt; after copying the other files, any small changes to these other files will install all Node dependencies again.&lt;/p&gt;

&lt;p&gt;Container is just another layer on top of it. So, because one image can have multiple containers, each one of them is a separated layer on top of the Dockerfile instructions.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to create images and containers
&lt;/h2&gt;

&lt;p&gt;The examples below are based on the Dockerfile of the section above, in a scenario where the Dockerfile is located in the root of the project and we are executing the Docker commands in the same directory level of this file.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating Docker images
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;docker build .&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Once the command above is run, and an image is created based on the Dockerfile, we can copy its generated id to be used to run the container. In case you need to check the image id after its creation, you can use &lt;code&gt;docker images&lt;/code&gt; to list all of them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating Docker containers
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;docker run -p 3000:80 -d --rm sha256:65597563a5b3d5b5b74dcc5e27256f015f8fc7a57f5adfc79e7c4517a156dcfd&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Here we have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the id of the image (the long hash at the end of the command - I’ll show how to manage images using custom names later)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-p 3000:80&lt;/code&gt; is used to enable a local port to access the project port from the Docker container&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-d&lt;/code&gt; to run the container in background, so the terminal will be free to run other commands&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--rm&lt;/code&gt; to delete the container as soon as it is stopped&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A more basic command would be:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;docker run -p 3000:80 sha256:65597563a5b3d5b5b74dcc5e27256f015f8fc7a57f5adfc79e7c4517a156dcfd&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Once a container is running, you can stop it. So you can list all the containers using &lt;code&gt;docker ps&lt;/code&gt; to list all the containers that are running, get the ID of the container you want to stop, and then run &lt;code&gt;docker stop 0401f0d42e86&lt;/code&gt;, where the hash in this example is the container ID.&lt;/p&gt;

&lt;h2&gt;
  
  
  Naming images and containers
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Naming Docker images
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker build -t [image_name]
docker build -t [image_name]:[tag_name] .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can use tags (&lt;code&gt;-t&lt;/code&gt;) to specify not only the image name but also its different versions, like &lt;code&gt;node:14&lt;/code&gt;, for example ("node" is the image name and "14" is the version of this image).&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker build -t sunflower .
docker build -t sunflower:latest .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These commands create an image called “sunflower” and also a version of it called “latest” (which can be numbers or any other word you want).&lt;/p&gt;

&lt;h3&gt;
  
  
  Renaming Docker images
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;docker tag [current_image_name]:[current_tag_name] [new_image_name]:[new_tag_name]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;docker tag sunflower:latest butterfly:latest&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This command will replace the image name “sunflower” to “butterfly”.&lt;/p&gt;

&lt;h3&gt;
  
  
  Naming Docker containers
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;docker run -p 3000:80 -d —rm —name [container_name] [image_name/id]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;docker run -p 3000:80 -d --rm —name myapp sunflower&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This command will create a container called “myapp” based on an image called “sunflower”.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sharing images
&lt;/h2&gt;

&lt;p&gt;There are two ways to share an image: sharing the Dockerfile or pushing the image to Docker hub by making it disposable in private or public repository.&lt;/p&gt;

&lt;p&gt;Bellow you can check out some steps to push a local image onto &lt;a href="https://hub.docker.com/" rel="noopener noreferrer"&gt;Docker hub&lt;/a&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;a href="https://hub.docker.com/" rel="noopener noreferrer"&gt;Docker hub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Login and access your repositories, and create a new one&lt;/li&gt;
&lt;li&gt;Your remote repository should match with your local image name.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;docker push [image_name]&lt;/code&gt; to push your image to Docker hub&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;docker push dionarodrigues/butterfly:latest&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Where "dionarodrigues" is my username in Docker hub and "/butterfly:latest" is the repository name. So, my local image should be called "dionarodrigues/butterfly:latest"&lt;/p&gt;

&lt;p&gt;And this is the command to use an existing image from Docker hub:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;docker pull [repository/image_name]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Example: &lt;code&gt;docker pull node&lt;/code&gt; or &lt;code&gt;docker pull dionarodrigues/butterfly:latest&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Managing data with Docker
&lt;/h2&gt;

&lt;p&gt;Basically, there are 3 ways to manage data inside docker:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Images&lt;/strong&gt;: when we create an image and copy the code into it from Dockerfile by using the command &lt;code&gt;COPY&lt;/code&gt;. Data will be locked, read-only, until the image is created again. So, even if we change the files we copied into the image, they will just be updated with the latest changes when the image is rebuilt again as they are a snapshot from the time the image was created.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Containers&lt;/strong&gt;: the data is stored when a container is running and destroyed when a container is deleted. The difference here is that we can manage files while the container is running, however it’s not easier as the data will be in memory. For example, we can have a form that will create a file when submitted which will be available to be accessed while its container is running. Don’t forget that it will be deleted along with the container.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Volumes&lt;/strong&gt;: are files and folders on our host machine (local environment, outside the containers) controlled by Docker that are mapped with folders inside the containers. Docker volumes can persist data even when containers are deleted. Let's take the same example of the file being created by a form submission: when this file is stored on a volume, it can be shared with other containers and will persist even after the container that generated that file is deleted.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bind Mounts&lt;/strong&gt;: Similar to volumes, where data persists independently of containers, but with Docker bind mount we control where files and directories to be mounted in containers are stored on our host machine and any changes made to this mapped data will be instantly reflected in the container while with volumes no. So this is the solution to be able to easily create/edit/delete files inside a container even if it is running. Imagine you have started a React application using Docker and you are editing the JSX files and these files are mapped into the container using bind mount so that you see the changes reflected in the interface as soon as you save the file changes, no need to build a new image for that.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Volumes
&lt;/h2&gt;

&lt;p&gt;As you saw in the section before, volumes are folders in our host machines, managed by Docker to persist data by mapping local with container folders.&lt;/p&gt;

&lt;p&gt;You can find a full example of how to create volumes in the next section called "How to create volumes and bind mounts", before let’s dive into the 2 ways to create them:&lt;/p&gt;

&lt;h3&gt;
  
  
  Anonymous volumes
&lt;/h3&gt;

&lt;p&gt;This kind of volume is attached to the container, so it will only be useful while the container exists, however it survives when the container stops to run. It can’t be shared across different containers.&lt;/p&gt;

&lt;p&gt;It’s useful when you need to keep a file inside the container untouched while you replace other files there, for example.&lt;/p&gt;

&lt;p&gt;To create anonymous volumes, we can add an instruction in the dockerfile:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;VOLUME [“/app/node_modules”]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Or run the command below along with the container command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;-v [folder_inside_container_to_be_persisted]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;-v /app/node_modules&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Named volumes
&lt;/h3&gt;

&lt;p&gt;By assigning a name to the volume during the container creation, this data can be persisted after the container is deleted and can also be shared across different containers.&lt;/p&gt;

&lt;p&gt;Once we name the volume, Docker will check if it already exists, and if yes, Docker will use it instead of creating a new one.&lt;/p&gt;

&lt;p&gt;A good example is when a container is running and a form is submitted and the application creates a file containing the form data and stores it in a folder called “/app/feedback”. So to keep this data (file) even after the container is deleted, we can use a named volume by passing the path of this file folder along with the name of the volume. Then this data can be used to start this container again or even when creating another container.&lt;/p&gt;

&lt;p&gt;To create named volume we run the command below along with the container command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;-v [volume_name]:[folder_inside_container_to_be_persisted]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;-v feedback:/app/feedback&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Bind Mounts
&lt;/h2&gt;

&lt;p&gt;Different of the other options, where Docker controls where the data is stored, now we have full control of it. With Docker Bind Mounts we map folders from our local environment with folder inside containers, which is amazing as now we can create/edit/delete files and see the changes instantly reflected in the container. By using this option the data will be persisted even after container deletion as the data will be in our host machine.&lt;/p&gt;

&lt;p&gt;For example, let's say you are working on a React project and want to use docker to start your project. With Docker bind mounts, you can map your project's folders and files with those inside the Docker container, so you can create/edit/delete any file or directory and see the changes in your browser instantly. That said, the container will use your local files, not those locked when the image was created or those created inside the container or those created Docker using volumes.&lt;/p&gt;

&lt;p&gt;To create bind mounts we run the command below along with the container command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;-v [full_path_of_our_machine_folder]:[folder_inside_container_to_be_maped_with_our_machine_folder]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;-v /Users/dionarodrigues/Documents/Development/my-project:/app&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Just a quick note: If you don't always want to use the full path, you can use these shortcuts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MacOS / Linux: &lt;code&gt;-v $(pwd):/app&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Windows: &lt;code&gt;-v "%cd%":/app&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;-v $(pwd):/app&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How to create volumes and bind mounts
&lt;/h2&gt;

&lt;p&gt;Although we have 3 different options (anonymous and named volumes and bind mounts), we can combine them to make sure all the data will be persisted when a container is created. Bellow is an example using all of them together:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;docker run -d -p 3000:80 --rm --name [container_name] -v [folder_inside_container_to_be_persisted] -v [volume_name]:[folder_inside_container_to_be_persisted] -v [full_path_of_our_machine_folder]:[folder_inside_container_to_be_maped_with_our_machine_folder] [image_name/id]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;docker run -d -p 3000:80 --rm --name myApp -v /app/node_modules -v feedback:/app/feedback -v "/Users/dionarodrigues/Documents/Development/my-project:/app" sunflower&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Or using shortcuts for the local machine path:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;docker run -d -p 3000:80 --rm --name myApp -v /app/node_modules -v feedback:/app/feedback -v $(pwd):/app sunflower:latest&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In this example we use anonymous volume (first &lt;code&gt;-v&lt;/code&gt; in the example) to prevent “node_modules” to be overwritten when we map all folders of our local machine with folders inside the container (bind mounts, third &lt;code&gt;-v&lt;/code&gt;). Named volume (second &lt;code&gt;-v&lt;/code&gt;) is used here as an example to persiste data created inside the container when it’s running, so that we can share this data with other containers or even initialise a container with this data (if it already exists).&lt;/p&gt;

&lt;p&gt;Like images and containers, you can manage volumes by listing them using &lt;code&gt;docker volume ls&lt;/code&gt; command to get their names and them delete them using &lt;code&gt;docker volume rm [volume_name]&lt;/code&gt; command or even deleting all unused volumes with &lt;code&gt;docker volume prune&lt;/code&gt; command.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The main concept in Docker is containers. Containers are completely isolated processes from our machines having all they need to run our projects code. Each container is independent and can be portable to anywhere, what means that the same container will run on the same way in local and production environments, for example, guaranteeing the same version of dependencies and the database.&lt;/p&gt;

&lt;p&gt;Docker containers are created based on Docker images (packages containing all files and configurations to run a container), which are created using instructions from Dockerfile.&lt;/p&gt;

&lt;p&gt;Data can be persisted using Docker Volumes and Docker Bind Mounts. While Docker controls where data on our host machine is stored, we control it using bind mounts, and the latest is the solution to manage file changes and have them instantly reflected in the container, good when we are running React application using Docker, for example, and editing JSX files.&lt;/p&gt;

&lt;p&gt;I hope you have learned a lot from this article. Let me know.&lt;br&gt;
See you next time! 😁&lt;/p&gt;

</description>
      <category>docker</category>
      <category>webdev</category>
      <category>devops</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Understanding the most important HTTP status codes</title>
      <dc:creator>Diona Rodrigues</dc:creator>
      <pubDate>Mon, 01 Jan 2024 17:51:10 +0000</pubDate>
      <link>https://forem.com/dionarodrigues/understanding-the-most-important-http-status-codes-566o</link>
      <guid>https://forem.com/dionarodrigues/understanding-the-most-important-http-status-codes-566o</guid>
      <description>&lt;p&gt;&lt;strong&gt;Maybe you never realized how difficult the web would be without HTTP status codes, or what a terrible place to work without them, did you? How would we know when a resource was not found (404) or when a page/url was permanently moved (301), for example?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There are more then 60 different status codes organized into 5 groups and maybe you have used just less then 5 as working as a developer. Stay with me and I'll explain to you the most important HTTP status codes and which ones you should keep in mind to better handle web API requests.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are HTTP status codes by the way?
&lt;/h2&gt;

&lt;p&gt;Okay, before we go through the status codes, let's recap what HTTP (Hypertext Transfer Protocol) is.&lt;/p&gt;

&lt;p&gt;Developed in the early 1990s, HTTP is the basis of the World Wide Web (www) and is basically a client-server protocol for transferring data: a client, such as a web browser, makes a request and the server sends a response to it.&lt;/p&gt;

&lt;p&gt;Over these more than 30 years, HTTP has been greatly improved, but it still maintains its initial purpose. Thus, when the server sends a response to the client, it also sends the status code of that response, which is made up of 3 digits, like 404, 500 and 302 for example.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnrvnphb4710l9gdm8cto.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnrvnphb4710l9gdm8cto.jpg" alt="Server response screenshot containing 200 Status Code" width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Most used status codes
&lt;/h2&gt;

&lt;p&gt;Status codes are organized into 5 different groups: informational, successful, redirection, client error, and server error.&lt;/p&gt;

&lt;h3&gt;
  
  
  1- Informational responses (100 – 199)
&lt;/h3&gt;

&lt;p&gt;Although status codes in this group indicate that the server is still processing the request, they are never used. So we can ignore them.&lt;/p&gt;

&lt;h3&gt;
  
  
  2- Successful responses (200 – 299)
&lt;/h3&gt;

&lt;p&gt;If you've ever dealt with API requests, you've probably used some of the 10 status codes in this group, as they indicate that the request was fulfilled successfully.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;200 - OK&lt;/strong&gt;: the most common, is a generic code and means the request was successful.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;201 - Created&lt;/strong&gt;: commonly sent after &lt;code&gt;POST&lt;/code&gt; requests, it means the new resource was created successfully.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3- Redirection messages (300 – 399)
&lt;/h3&gt;

&lt;p&gt;As the name suggests, in this group you will find two of the most used status codes to indicate that the page or resource has been moved.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;301 - Moved Permanently&lt;/strong&gt;: means the page or resource has been permanently moved to another URL. Since the new URL can be found in the response, browsers will automatically redirect users. Search engines also use this response to associate the content of the old URL with the new one, in order to maintain its SEO ranking. Examples of this status code are when the site has been migrated to a new domain or changed from &lt;code&gt;HTTP&lt;/code&gt; to &lt;code&gt;HTTPS&lt;/code&gt;, for example.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;302 - Found&lt;/strong&gt;: similar to above, but means the page or resource has been temporarily moved. The biggest difference here is that search engines will keep the old URL indexed and show it in search results. Good examples of this code are: A/B testing (when we show different versions of a page to test its design or some functionality) and when we redirect the user to a version of the website based on location/language.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4- Client error responses (400 – 499)
&lt;/h3&gt;

&lt;p&gt;Among its almost 30 client error status codes here you will also find the most common ones used when dealing with API requests.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;401 - Unauthorized&lt;/strong&gt;: in fact, it means that the client is not authenticated when this is necessary to obtain the requested response.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;403 - Forbidden&lt;/strong&gt;: it's about permissions. So here the server informs that the client does not have permission to make this request, even if the client is authenticated. A good example is when a generic system user tries to load an admin route.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;404 - Not Found&lt;/strong&gt;: means that the page or resource was not found. Very common when we try to access a URL that doesn't exist. Sites often have a custom page to alert users about this with phrases like “Page not found”.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;429 - Too Many Requests&lt;/strong&gt;: when the client has exceeded the allowed number of HTTP requests. For example, when the server limits the number of API calls per hour.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5- Server error responses (500 – 599)
&lt;/h3&gt;

&lt;p&gt;Similar to the previous group, but here the status codes are related to some issue on the server, not on the client.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;500 Internal Server Error&lt;/strong&gt;: the most famous code in this group indicates that a problem occurred on the server when trying to make a request. It's very generic, so it could be anything. Sites also usually have a custom page to alert users about this with phrases like “Internal Server Error”.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status" rel="noopener noreferrer"&gt;HTTP response status codes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Overview" rel="noopener noreferrer"&gt;An overview of HTTP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.cloudflare.com/learning/ddos/glossary/hypertext-transfer-protocol-http/" rel="noopener noreferrer"&gt;What is in an HTTP request?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ahrefs.com/blog/301-vs-302-redirects/" rel="noopener noreferrer"&gt;301 vs. 302 Redirects for SEO: Which Should You Use?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/500" rel="noopener noreferrer"&gt;500 Internal Server Error&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dribbble.com/search/404-not-found" rel="noopener noreferrer"&gt;Creative examples of 404 Not Found pages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dribbble.com/search/500-server-error" rel="noopener noreferrer"&gt;Creative examples of 500 Server Error pages&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;As you can see from this article, there are not many HTTP status codes to keep in mind when working with client/API requests so that they are easy to remember over time. By knowing the ones I described here, you will be able to better deal with server responses, improving your code, helping search engines to index the site and also delivering a better user experience as you will be able to display customized pages depending on the status code.&lt;/p&gt;

&lt;p&gt;See you next time! 😁&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>api</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
