<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Diona Rodrigues</title>
    <description>The latest articles on DEV Community by Diona Rodrigues (@dionarodrigues).</description>
    <link>https://dev.to/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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F393945%2F0a921add-d1a4-40e2-8e38-a8410465f3ef.jpg</url>
      <title>DEV Community: Diona Rodrigues</title>
      <link>https://dev.to/dionarodrigues</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dionarodrigues"/>
    <language>en</language>
    <item>
      <title>Kiro and the Future of AI-Assisted Development</title>
      <dc:creator>Diona Rodrigues</dc:creator>
      <pubDate>Mon, 27 Jul 2026 17:39:49 +0000</pubDate>
      <link>https://dev.to/dionarodrigues/kiro-and-the-future-of-ai-assisted-development-4nam</link>
      <guid>https://dev.to/dionarodrigues/kiro-and-the-future-of-ai-assisted-development-4nam</guid>
      <description>&lt;p&gt;I started using Kiro at work and am incredibly impressed by how it transforms our AI coding workflow. Instead of writing code first and refactoring later (the typical loop with Copilot and ChatGPT), Kiro uses a spec-driven approach.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Kiro methodology — moving from requirements to technical design to tasks — perfectly solves a challenge I had been trying to fix with GitHub Copilot. I wanted a way to define structured instructions first and then generate the code, but Kiro automates that whole initial planning phase for me.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Below are my first impressions of Kiro after a few weeks of hands-on use. If you are currently using GitHub's AI tool, you can also check out my other article for some &lt;a href="https://dev.to/dionarodrigues/11-ways-to-supercharge-your-workflow-with-github-copilot-ee"&gt;great ways to supercharge your workflow with Github Copilot&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Kiro?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Kiro is an Integrated Development Environment (IDE) built by AWS on the open-source version of VS Code (&lt;a href="https://github.com/Microsoft/vscode" rel="noopener noreferrer"&gt;Code OSS&lt;/a&gt;)&lt;/strong&gt; - so it combines all the VS Code advantages and extensions with a built-in AI tool optimized for spec-driven development. Unlike traditional AI assistants that generate code from chat prompts, Kiro focuses on specifications first. You define the blueprint, turn it into a clear list of tasks, and then decide whether to run them one by one or all at once.&lt;/p&gt;

&lt;h2&gt;
  
  
  Kiro Agents
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Kiro agents use the same concept as Copilot agents: they are autonomous, specialized AI assistants that you can choose based on the specific task you want help with&lt;/strong&gt;. Kiro also comes with a few built-in agents that you can select when starting a new chat session, and you can also create your own agents:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Spec&lt;/strong&gt;: Focuses on the planning phase to map out feature requirements, technical design and tasks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Plan&lt;/strong&gt;: Analyzes the codebase to help you to resolve questions you have and plan how to coordinate the coding workflow.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bug Fix&lt;/strong&gt;: Debugs your code by catching errors and applying immediate corrections.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note: Depending on the version of Kiro you are using, you may see a slightly different set of agents, but the Spec agent is the one we will focus on in this article.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;AGENTS.md&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;This file is used by AI tools in every chat interaction, so it is worth setting up properly. To unlock Kiro's full power, create an &lt;code&gt;AGENTS.md&lt;/code&gt; file at your project root. It should capture the main system requirements, such as those provided by the architecture team, along with any important tech stack constraints and the essential commands for the project. Keep it concise and avoid over-explaining or redundancy. You can find examples at &lt;a href="https://agents.md/" rel="noopener noreferrer"&gt;agents.md&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Kiro specs
&lt;/h2&gt;

&lt;p&gt;This is where Kiro really shines. The workflow for &lt;a href="https://kiro.dev/docs/specs/" rel="noopener noreferrer"&gt;Kiro specs&lt;/a&gt; follows a recommended path: &lt;strong&gt;Requirements → Design → Tasks&lt;/strong&gt;. These files are created before any code changes are made. While you can technically skip ahead and start with Design, Kiro strongly advises beginning with Requirements. Whichever path you choose, Kiro automatically saves these files inside a dedicated feature folder within a hidden &lt;code&gt;.kiro/&lt;/code&gt; directory at your project root.&lt;/p&gt;


    
    Your browser does not support the video tag. You can also &lt;a href="https://kiro.dev/videos/spec-task.mp4?h=66bfe3fb" rel="noopener noreferrer"&gt;watch the video on Kiro's site&lt;/a&gt;.


&lt;p&gt;&lt;em&gt;Source: Kiro documentation.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The idea here is to create specs grouped by feature. Each feature could correspond to a Jira ticket, for example. This is different from &lt;code&gt;AGENTS.md&lt;/code&gt;, which contains the core instructions for the project. In this case, we ask Kiro to focus on the specific parts of the project we are implementing.&lt;/p&gt;

&lt;p&gt;Let's dive into them below.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;Requirements.md&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;This is your entry point: Kiro will generate a clear list of user stories and constraints that is easy for anyone to read.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To create the spec, make sure the Spec agent is active (you can select it whenever you start a new chat session, as explained above). Then ask Kiro to define the requirements, clearly stating what should and should not be implemented at this stage. For example, you can base the instructions on the Jira ticket requirements. Kiro will ask whether this is a new feature and, if so, group related specs into a new folder within &lt;code&gt;.kiro/&lt;/code&gt;. Keep your instructions narrow and precise.&lt;/p&gt;

&lt;p&gt;For example, imagine a web app with several features. The &lt;code&gt;AGENTS.md&lt;/code&gt; file would hold the core project requirements, while &lt;strong&gt;a chat prompt could ask Kiro to create requirements for a new feature, such as: "Create the requirements for a new feature. It should focus on X, but should not include Y." Here, X and Y are short lists of things to include or exclude.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once the initial draft is ready, Kiro will ask whether you want to refine the requirements. If so, it will prompt you with a series of refinement questions to improve the document, or you can ask it to apply the necessary changes directly.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;Design.md&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Once the requirements are locked, Kiro asks for permission to move on to the technical design phase. Based on the requirements, it generates technical blueprints tailored to your stack — data models, infrastructure needs, example code snippets, and component diagrams.&lt;/p&gt;

&lt;p&gt;Concrete examples Kiro can produce:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Folder structure and file names it will create (so you can review layout before code is written).&lt;/li&gt;
&lt;li&gt;TypeScript interfaces or JSON schemas for the data models the feature will use.&lt;/li&gt;
&lt;li&gt;API contract examples (endpoints, request/response shapes) or OpenAPI fragments.&lt;/li&gt;
&lt;li&gt;Small, runnable code snippets or migration scripts the agents will apply.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As before, review these outputs and make any adjustments before moving on to the implementation tasks.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;Tasks.md&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;In this final step, Kiro converts your technical design into a dependency-aware checklist of implementation tasks.&lt;/strong&gt; Tasks are grouped by step so you can follow the implementation flow (see the video above for a demo). Click on a task to apply it and watch progress in the UI: an animated icon shows work in progress and a checkmark appears when the task completes.&lt;/p&gt;

&lt;p&gt;You can run tasks one-by-one, by group, or all at once. I recommend running them individually or in small groups so you can review changes as they happen and request improvements if needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Additional Kiro features
&lt;/h2&gt;

&lt;p&gt;Kiro includes several other useful features — check the official documentation for full details.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://kiro.dev/docs/chat/autopilot/" rel="noopener noreferrer"&gt;Autopilot&lt;/a&gt;&lt;/strong&gt;: gives you control over how the AI applies changes. You can run everything automatically in Autopilot mode, or approve each step manually in Supervised mode.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://kiro.dev/docs/steering/" rel="noopener noreferrer"&gt;Steering&lt;/a&gt;&lt;/strong&gt;: similar to Copilot, Kiro lets you define rules for specific contexts using frontmatter in Markdown files. For example, you can create custom instructions for TypeScript files only. These instructions can be applied automatically or manually through the chat prompt and can target the repository, workspace, or global level.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://kiro.dev/docs/chat/slash-commands/" rel="noopener noreferrer"&gt;Slash commands&lt;/a&gt;&lt;/strong&gt;: let you run custom instructions from chat. For example, you could create a steering rule or hook that generates a commit message whenever you type &lt;code&gt;/create-commit-msg&lt;/code&gt;, then analyze the diff and suggest a concise message that follows your preferred pattern.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://kiro.dev/docs/chat/checkpoints/" rel="noopener noreferrer"&gt;Checkpoints&lt;/a&gt;&lt;/strong&gt;: because Kiro creates checkpoints throughout a chat, you can click "Restore" to rewind both your code changes and the Kiro context. It is essentially an undo button.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://kiro.dev/docs/custom-agents/" rel="noopener noreferrer"&gt;Custom agents&lt;/a&gt;&lt;/strong&gt;: as mentioned before, Kiro comes with some prebuilt agents, but you can also create your own for specific needs, such as a developer agent with tailored instructions. This agent will then be available when you start a new session.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;What I like most about Kiro is that it feels less like a chatbot and more like a thoughtful collaborator. It has helped me structure my work better and stay more intentional about the code I write, especially as I move from refactoring to planning. If you enjoy building with AI in a more guided way, I think it is absolutely worth trying. 😊&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>productivity</category>
    </item>
    <item>
      <title>11 Ways to supercharge your workflow with GitHub Copilot</title>
      <dc:creator>Diona Rodrigues</dc:creator>
      <pubDate>Sun, 05 Jul 2026 17:26:40 +0000</pubDate>
      <link>https://dev.to/dionarodrigues/11-ways-to-supercharge-your-workflow-with-github-copilot-ee</link>
      <guid>https://dev.to/dionarodrigues/11-ways-to-supercharge-your-workflow-with-github-copilot-ee</guid>
      <description>&lt;p&gt;&lt;strong&gt;Coding isn't just about writing code. Tasks like reading old logic, formatting Git commits, and finding terminal commands steal your development time. GitHub Copilot promises to change that, but basic prompts often give generic, wrong results.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To turn Copilot into a highly specialized assistant, you need to feed it the right context. This guide explores the best hidden features using, custom AI rules, and workflow shortcuts to help you develop code faster inside Visual Studio Code.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Note: You must manually &lt;a href="https://code.visualstudio.com/docs/setup/copilot" rel="noopener noreferrer"&gt;install the GitHub Copilot&lt;/a&gt; extension and link it to a free or paid plan to follow along).&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Be Specific: Your Secret to Better Code
&lt;/h2&gt;

&lt;p&gt;The instructions you give to Copilot are the secret to getting great results. &lt;strong&gt;When you write vague prompts, the AI is forced to guess what you want, which usually leads to errors&lt;/strong&gt;. It is much faster to spend time writing clear instructions upfront than it is to rewrite broken code later. If you have a complex task, you can even use tools like ChatGPT to help you plan out the perfect, detailed prompt before you paste it into Copilot.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❌ &lt;strong&gt;Poor Prompt (Too Generic)&lt;/strong&gt;: “Create a signup function for my app."&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Good Prompt (Specific and Clear)&lt;/strong&gt;: "Create a JavaScript function for user signup using Node.js and Express. It must collect a name, email, and password. Hash the password using bcrypt before saving it to a MongoDB database. Return a 400 error if the email already exists."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The more detailed the prompt, the better. For bigger tasks — like building pages with different components, following specific coding standards, and then adding tests — break the request into clear steps. ChatGPT can really help organize that prompt so Copilot understands it.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Debug your UI with Copilot directly inside VS Code
&lt;/h2&gt;

&lt;p&gt;VS Code features an integrated browser that lets you run and test your web application without leaving the editor. When paired with Copilot, this feature turns into a powerful AI-driven debugging assistant. You can inspect UI elements, capture them, and immediately ask Copilot to rewrite the code and apply the fix. &lt;a href="https://code.visualstudio.com/docs/debugtest/integrated-browser" rel="noopener noreferrer"&gt;Learn how to set up the integrated browser&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Custom rules files for the AI
&lt;/h2&gt;

&lt;p&gt;Instead of typing out instructions every time you use the prompt chat, you can &lt;a href="https://docs.github.com/en/copilot/how-tos/copilot-on-github/customize-copilot/add-custom-instructions/add-repository-instructions" rel="noopener noreferrer"&gt;save rule files, in Markdown format, directly inside your project&lt;/a&gt;. Copilot natively supports three specific types of markdown configuration files within your project space:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;AGENTS.md&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Placed directly at the root of your project. It is becoming the universal multi-agent standard, and VS Code detects it automatically for every chat request. Keep it short, and document your tech stack, project structure, build/test commands, and non-obvious tooling (e.g., &lt;code&gt;uv&lt;/code&gt; instead of &lt;code&gt;pip&lt;/code&gt; for Python, &lt;code&gt;pnpm&lt;/code&gt; instead of &lt;code&gt;npm&lt;/code&gt; for JavaScript). Avoid detailed directory listings, code style guidelines, and task-specific instructions — they dilute focus and don't help agents navigate faster. Find examples at &lt;a href="https://agents.md/" rel="noopener noreferrer"&gt;agents.md&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;.github/copilot-instructions.md&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This file is specific to Copilot and lives at &lt;code&gt;.github&lt;/code&gt; directory in the repository root. It is optional if you already have a root &lt;code&gt;AGENTS.md&lt;/code&gt;; when both files exist their instructions are combined, so avoid repeating the same rules. Root &lt;code&gt;AGENTS.md&lt;/code&gt; entries are generally treated as primary and often have more influence than additional instructions found elsewhere.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;.github/instructions/NAME.instructions.md&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Use these for granular, path-specific custom instructions such as &lt;code&gt;react.instructions.md&lt;/code&gt; or &lt;code&gt;database.instructions.md&lt;/code&gt;. Copilot applies them only when the current file path matches the &lt;code&gt;applyTo&lt;/code&gt; pattern declared in the frontmatter at the top of the file. For example, set &lt;code&gt;applyTo: "**/*.{ts,tsx}"&lt;/code&gt; to target TypeScript files only. Learn how to create path-specific instructions in the Copilot docs &lt;a href="https://docs.github.com/en/copilot/how-tos/copilot-cli/customize-copilot/add-custom-instructions#creating-path-specific-custom-instructions" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Use Copilot in your terminal
&lt;/h2&gt;

&lt;p&gt;Install &lt;a href="https://cli.github.com/" rel="noopener noreferrer"&gt;GitHub CLI&lt;/a&gt; and run &lt;code&gt;gh copilot&lt;/code&gt; to get AI command help, verify syntax, and simplify GitHub workflows from the shell. It’s a great way to keep working in one place while still getting quick guidance on commands and workflow steps.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Generate code faster with inline chat
&lt;/h2&gt;

&lt;p&gt;Use &lt;a href="https://code.visualstudio.com/docs/chat/inline-chat" rel="noopener noreferrer"&gt;Copilot Inline Chat&lt;/a&gt; to ask for code, refactors, or fixes right where you are. Right-click and choose Open Inline Chat, or press &lt;code&gt;Cmd + I&lt;/code&gt; on Mac / &lt;code&gt;Ctrl + I&lt;/code&gt; on Windows, and stay focused on the current line instead of bouncing to a separate panel.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Slash commands for faster help
&lt;/h2&gt;

&lt;p&gt;Slash commands are very useful and can make Copilot feel more like a command palette for chat. Type &lt;code&gt;/&lt;/code&gt; in a chat or inline chat window to see actions like &lt;code&gt;/explain&lt;/code&gt;, &lt;code&gt;/fix&lt;/code&gt;, and &lt;code&gt;/tests&lt;/code&gt;, then add a few words to narrow the result.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Quick fix:&lt;/strong&gt; Type &lt;code&gt;/fix&lt;/code&gt; to ask Copilot to repair the current selection.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Targeted review:&lt;/strong&gt; Type &lt;code&gt;/explain&lt;/code&gt; plus a prompt like &lt;code&gt;Focus on the security implications&lt;/code&gt; for a more specific answer.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Create Custom Prompts for Repetitive Tasks
&lt;/h3&gt;

&lt;p&gt;You can customize slash commands by creating reusable prompt instruction files with extra context. They can automate repetitive work such as code migrations, test generation, security checks, or README updates. Save them in &lt;code&gt;.github/prompts/&lt;/code&gt; as &lt;code&gt;NAME.prompt.md&lt;/code&gt;, for example &lt;code&gt;readme.prompt.md&lt;/code&gt;. Read more about prompt files &lt;a href="https://docs.github.com/en/copilot/concepts/prompting/response-customization?tool=vscode#about-prompt-files" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Quick code explanation, review, and fix
&lt;/h2&gt;

&lt;p&gt;Get help with a block of code instantly, without writing a long prompt. Select the code you want to work with and Copilot will surface smart actions to explain, review, or fix it for you. This is often the fastest way to understand legacy logic, uncover hidden bugs, or clean up messy formatting.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Right-click menu&lt;/strong&gt;: Highlight your code, right-click, and choose Explain, Review, or Fix.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lightbulb icon&lt;/strong&gt;: Highlight your code and click the yellow lightbulb icon in the editor gutter (left margin) to access the same AI quick actions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  8. Commit messages generated by the AI
&lt;/h2&gt;

&lt;p&gt;Writing good git commit messages takes time, but Copilot can write them for you based on your actual file changes. Inside the Source Control panel, simply click the sparkling Sparkle/Stars icon on the right side of the commit message input box. Copilot will analyze your staged changes and generate a clear, meaningful message that you can review, edit, and approve before committing.&lt;/p&gt;

&lt;p&gt;You can make Copilot follow a style guide—like including Jira ticket numbers — by adding rules to your global &lt;code&gt;settings.json&lt;/code&gt;.&lt;br&gt;
For example, ask it to prefix commit messages with the current Git branch name:&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="nl"&gt;"github.copilot.chat.commitMessageGeneration.instructions"&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;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"The commit message must strictly follow this format: [branch-name] [commit-message]. Read the active branch name from the provided context file. Follow the closing bracket with exactly one space, then a short summary."&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;"file"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;".git/HEAD"&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="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  9. Choose the best AI model for your task
&lt;/h2&gt;

&lt;p&gt;Copilot can use different models, even on the free plan, such as GPT-5, Claude, or Gemini. Pick the one that fits your goal — code generation, debugging, architecture — then choose it from the model selector in the VS Code chat panel controls at the bottom. &lt;a href="https://docs.github.com/en/copilot/reference/ai-models/supported-models" rel="noopener noreferrer"&gt;Learn more about supported models&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Copilot Agents
&lt;/h2&gt;

&lt;p&gt;Agents let you choose how Copilot helps you. Use the agent mode control in the bottom of the VS Code chat pane and pick one of these built-in options (available options may change over time):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Agent&lt;/strong&gt;: The default and most powerful mode. It can run terminal commands, test code, edit files, and handle broader tasks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ask&lt;/strong&gt;: A lighter mode for questions and suggestions about the code. It is ideal for quick examples, guidance, and test advice.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Plan&lt;/strong&gt;: Best when you want to break a complex task into smaller steps before asking the AI to apply changes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can also &lt;a href="https://docs.github.com/en/copilot/how-tos/copilot-on-github/customize-copilot/customize-cloud-agent/create-custom-agents" rel="noopener noreferrer"&gt;create custom agents&lt;/a&gt; for specialized workflows.&lt;/p&gt;

&lt;h2&gt;
  
  
  11. Help Copilot stay focused.
&lt;/h2&gt;

&lt;p&gt;Avoid mixing different tasks in one chat window, as combining multiple subjects dilutes the AI's contextual awareness and leads to hallucinated logic. Instead, open a fresh session for each feature—such as one distinct window for authentication and another for WebSocket protocols. That keeps your prompt environment clean and improves the accuracy of result.&lt;/p&gt;

&lt;p&gt;Learn how to create and switch between threads in the &lt;a href="https://code.visualstudio.com/docs/chat/chat-sessions" rel="noopener noreferrer"&gt;VS Code Manage Chat Sessions guide&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;GitHub Copilot works best when you give it clear instructions and keep each chat focused. Use project rule files, terminal AI commands, and the right model or agent for the task. &lt;strong&gt;Better prompts lead to better code.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>productivity</category>
    </item>
    <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://dev.to/dionarodrigues/why-clean-code-matters-lessons-from-uncle-bob-137l</link>
      <guid>https://dev.to/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://dev.to/dionarodrigues/essential-sql-commands-a-quick-reference-guide-59ff</link>
      <guid>https://dev.to/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://dev.to/dionarodrigues/redux-toolkit-advanced-scaling-redux-toolkit-for-large-applications-gb</link>
      <guid>https://dev.to/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://dev.to/dionarodrigues/redux-toolkit-fundamentals-simplifying-state-management-41m4</link>
      <guid>https://dev.to/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://dev.to/dionarodrigues/nvm-basics-bash-aliases-simplify-your-development-workflow-202g</link>
      <guid>https://dev.to/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://dev.to/dionarodrigues/from-useeffect-to-react-query-modernizing-your-data-management-in-react-1a6a</link>
      <guid>https://dev.to/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://dev.to/dionarodrigues/web-accessibility-how-to-design-web-pages-for-everyone-4k75</link>
      <guid>https://dev.to/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&amp;nbsp;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://dev.to/dionarodrigues/6-useful-css-features-you-might-not-know-about-4cjg</link>
      <guid>https://dev.to/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&amp;nbsp;“color”&amp;nbsp;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&amp;nbsp;behind&amp;nbsp;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://dev.to/dionarodrigues/docker-compose-orchestrating-and-automating-services-3ajg</link>
      <guid>https://dev.to/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://dev.to/dionarodrigues/docker-networking-how-to-connect-different-containers-364d</link>
      <guid>https://dev.to/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>
  </channel>
</rss>
