<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Felix Owino</title>
    <description>The latest articles on Forem by Felix Owino (@ghostaram).</description>
    <link>https://forem.com/ghostaram</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1064262%2Feaf8682a-9c21-48a9-9fcd-3fd60f075f63.jpeg</url>
      <title>Forem: Felix Owino</title>
      <link>https://forem.com/ghostaram</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/ghostaram"/>
    <language>en</language>
    <item>
      <title>Writing meaningful Git commit messages with semantic tags</title>
      <dc:creator>Felix Owino</dc:creator>
      <pubDate>Fri, 02 Aug 2024 17:34:10 +0000</pubDate>
      <link>https://forem.com/ghostaram/writing-meaningful-git-commit-messages-with-semantic-tags-1dim</link>
      <guid>https://forem.com/ghostaram/writing-meaningful-git-commit-messages-with-semantic-tags-1dim</guid>
      <description>&lt;p&gt;In version control systems like Git, commit messages are the best way to document your development progress. Commit messages tell other developers what you have done for each change you make in your code base. It's not just about other developers though, commit messages are important to you as well. Let's say you want to know what you did yesterday, how, and why, the commit messages history will always be your friend. Considering how important commit messages are in the sphere of software development, we cannot ignore the need to keep them clear and meaningful. Commit messages are important but not if they don't make sense. In this article, we will discuss how to write commit messages that clearly communicate changes and don't leave you or other developers wondering what happened during that change.&lt;/p&gt;

&lt;p&gt;A well-written commit message has three parts: the commit &lt;strong&gt;tag&lt;/strong&gt;, the &lt;strong&gt;subject&lt;/strong&gt;, and the &lt;strong&gt;body&lt;/strong&gt;. The tag classifies the change to a particular category. The subject declares the change in a single statement. The commit message body provides more details about the change. Look at the following commit message for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; refactor: Validate reference IDs after authenticating routes

          - Move the Reference ID validators and
            validation error handlers below the authentication
            middleware in the routes where ID is required
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above commit message, &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The word &lt;code&gt;refactor&lt;/code&gt; is the message &lt;strong&gt;tag&lt;/strong&gt; that classifies the change as a refactor (We will talk more about tags shortly). &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The statement &lt;em&gt;'Validate reference ids  after authenticating routes'&lt;/em&gt; is the &lt;strong&gt;subject&lt;/strong&gt; of the message.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The longer sentence below the subject is the message body.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you had no idea that a commit message has three parts, you can now see why that is so and appreciate their importance. The tag classifies the change. The subject tells you what the change is about without boring you with the details. Finally, the body outlines the details of the change.&lt;/p&gt;

&lt;p&gt;In this article, we will talk about the semantic tag.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Semantic tag.
&lt;/h2&gt;

&lt;p&gt;The semantic tag helps to clarify what the change is about by classification. There are several semantic tags that can be used to classify changes in commit messages. Here are some of the tags that I have used and you can use too:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;feat&lt;/li&gt;
&lt;li&gt;refactor&lt;/li&gt;
&lt;li&gt;fix&lt;/li&gt;
&lt;li&gt;breaking&lt;/li&gt;
&lt;li&gt;test&lt;/li&gt;
&lt;li&gt;chore&lt;/li&gt;
&lt;li&gt;revert&lt;/li&gt;
&lt;li&gt;docs&lt;/li&gt;
&lt;li&gt;style&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The question you are probably asking yourself now is "What do these tags mean and how will I know when and where to use which one?". Relax, We have got you covered. Before the end of this article, We will have talked all about the above tags, what they mean, and when and where to use them. We will also throw in a few examples for you to see how you can use them in practice. Happy now? Let's get started with the &lt;code&gt;feat&lt;/code&gt; tag.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The &lt;code&gt;feat&lt;/code&gt; tag
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;feat&lt;/code&gt; tag is used to classify a change that introduces a new feature or functionality in the system you are building. This is the tag you use on a commit message when the change you have just made has introduced a behavior that didn't exist in the system before. &lt;/p&gt;

&lt;p&gt;For example, you are building an app that accepts user input and stores the data in a database. The system is working as expected, then you decide to validate user input. Now users can only input data that the system agrees with. The system will reject the data it considers invalid and accept only the data it considers valid. This is a behavior that did not exist earlier. The change has introduced a new behavior in the system. It is therefore classified as a &lt;code&gt;feat&lt;/code&gt;. In this case, you will write your commit message as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;feat: Validate user input


     - Ensure users enter valid data before accepting their input
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's that simple, now you can spot a change that introduced something new without reading any further than the &lt;code&gt;feat&lt;/code&gt; tag.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. The &lt;code&gt;refactor&lt;/code&gt; tag
&lt;/h3&gt;

&lt;p&gt;Away from Git commit messages, refactoring code normally means changing the implementation of a program in a way that does not alter its behavior. For example, replacing double quotes with single quotes in a string initialization.&lt;/p&gt;

&lt;p&gt;In relation to git commit messages, a change is classified as a &lt;code&gt;refactor&lt;/code&gt; if the implementation of a program has changed but the program still does exactly what and how it was doing before the change.&lt;/p&gt;

&lt;p&gt;For example, say you have a function that takes an array of numbers and returns the sum of the numbers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function sumArray(numbers) {
    let sum = 0;
    for (let i = 0; i &amp;lt; numbers.length; i++) {
        sum += numbers[i];
    }
    return sum;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you decide to do something more simplified like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function sumArray(numbers) {
    return numbers.reduce((sum, number) =&amp;gt; sum + number, 0);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You see, you have reduced the implementation of the same function from 6 lines of code to 1 line and you still achieve the same goal. In this case, you would have a commit message that reads as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;refactor: Change the implementation of the sumArray function to a more
          simplified one

          - simplify the sumArray function using Array.reduce method
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Changes that can be classified as &lt;code&gt;refactor&lt;/code&gt; are not just limited to simplifying implementations of functions. The following changes can also be classified as &lt;code&gt;refactor&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Renaming variables, functions, methods, or classes&lt;/li&gt;
&lt;li&gt;Removing redundant utility functions&lt;/li&gt;
&lt;li&gt;Extracting code into reusable functions or methods&lt;/li&gt;
&lt;li&gt;Splitting a large function into smaller functions with single responsibilities&lt;/li&gt;
&lt;li&gt;Replacing a library with another library that achieves the same purpose&lt;/li&gt;
&lt;li&gt;Optimizing functionalities without changing their outputs&lt;/li&gt;
&lt;li&gt;Reorganizing code logical structure or execution order without changing the output&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The list of changes that can be classified as a &lt;code&gt;refactor&lt;/code&gt; is endless. The most important thing to remember is that a &lt;code&gt;refactor&lt;/code&gt; is any change that alters the code without adding, eliminating, or altering a functionality in your system.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. The &lt;code&gt;fix&lt;/code&gt; tag.
&lt;/h3&gt;

&lt;p&gt;Just like it sounds, the &lt;code&gt;fix&lt;/code&gt; tag is used to classify changes that fix problems in the system. Problems can be bugs, issues, errors, crashes, etc. &lt;/p&gt;

&lt;p&gt;Now assume you are building an app that authenticates users before allowing access. The authentication works, unregistered users cannot access the system. That's what you want but you also have another behavior you don't want. Registered users cannot access the system either. Your registered users enter their correct emails and passwords but the system keeps saying the password is wrong. &lt;/p&gt;

&lt;p&gt;You look through your code and realize that you are encrypting the user's password twice before saving it but decrypting once when trying to log in. Twice how? Once in the login controller and again in the User schema just before saving the new user document to the database. &lt;/p&gt;

&lt;p&gt;You are relieved after finding out the problems. You remove the encryption at the controller and remain with one encryption process, at the data schema. Now new users can register and log in smoothly with their correct credentials.&lt;/p&gt;

&lt;p&gt;The change in the paragraph above fixes an issue in the authentication of the system. This is the kind of change you classify as a &lt;code&gt;fix&lt;/code&gt; and the commit message can read as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fix: Resolve the issue preventing registered users from logging in with 
      correct credentials

    - Remove double encryption of user password during registration
    - Remove the encryption of passwords in the user registration
      controller and use the encryption in the user schema only.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above commit message communicates what it does very clearly. You can spot the change that fixed a problem in the system without reading the whole commit message. That is how useful the &lt;code&gt;fix&lt;/code&gt; tag can be.&lt;/p&gt;

&lt;p&gt;An authentication issue fix is only one of the many kinds of changes that can be classified as a &lt;code&gt;fix&lt;/code&gt;. The following kinds of changes can also be considered as &lt;code&gt;fix&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Handling uncaught exceptions and errors&lt;/li&gt;
&lt;li&gt;Handling rejected Promises&lt;/li&gt;
&lt;li&gt;Implementing global error handlers to prevent an application from crushing due to unexpected errors&lt;/li&gt;
&lt;li&gt;Correcting logical errors in calculation algorithms&lt;/li&gt;
&lt;li&gt;Taking care of compatibility issues across browsers in web apps&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. The &lt;code&gt;breaking&lt;/code&gt; tag
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;breaking&lt;/code&gt; tag is used to classify breaking changes. Breaking changes are a little like refactors in that they do not introduce new functionalities to your system or codebase but they are more impactful than refactors. A breaking change forces changes in other parts of the system that depend on the part that has been changed. They break backward compatibility in systems and codebases. If a breaking change occurs in one component in the system, every component that depends on the changed component has to be updated as well.&lt;/p&gt;

&lt;p&gt;An example can explain it better. Assume you have a base controller class called &lt;code&gt;BaseController&lt;/code&gt; in the libraries folder of your system. The &lt;code&gt;BaseController&lt;/code&gt; class has a constructor that accepts one parameter. Your system has 6 apps namely users, events, venues, venue types, event categories, and authenticator. Each of the six apps in the system has a controller class that inherits the &lt;code&gt;BaseController&lt;/code&gt; class and implements a constructor. &lt;/p&gt;

&lt;p&gt;You have decided to change the constructor of the &lt;code&gt;BaseController&lt;/code&gt; class by adding one more parameter called &lt;code&gt;appName&lt;/code&gt;. Now all the classes that extend the &lt;code&gt;BaseController&lt;/code&gt; must update their constructors to match the new implementation. All the apps in the system will be affected because of one change in the base class. This is what we call a &lt;code&gt;breaking&lt;/code&gt; change. The above change can be committed as follows.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;breaking: Update the BaseController constructor to accept two 
          parameters

          - Add a new parameter called appName to the constructor of 
            the base controller class
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sense? Yes. Altering the constructor of a base class is not the only kind of change that can be classified as a &lt;code&gt;breaking&lt;/code&gt; change, here are a few more:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adding a method or a field to an interface that is implemented by other components in the system or codebase.&lt;/li&gt;
&lt;li&gt;Changing the return type of a method in a base class&lt;/li&gt;
&lt;li&gt;Changing the structure or properties in a database schema&lt;/li&gt;
&lt;li&gt;Renaming or removing a public method from a class&lt;/li&gt;
&lt;li&gt;Altering method signatures by modifying the type of parameters, reducing or increasing the number of parameters in a function or a method.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's it about &lt;code&gt;breaking&lt;/code&gt; changes but not all. These are changes that demand attention from other parts of the system. In a development team, the impact of the change can go as far as affecting other developers' work too. When they pull the breaking changes, they will be forced to update their components that depend on the changed entity.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. The &lt;code&gt;test&lt;/code&gt; tag
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;test&lt;/code&gt; tag is related to the practice of test-driven development. In test-driven development, we are always encouraged to write a failing test before we finish implementing a function, class, or whatever it is we are writing code for. Every time you write a test, you create a change you want to commit before you continue working on the implementation of the test subject. All changes related to tests are classified as &lt;code&gt;test&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Say you are building a backend system, you want to implement POST route handlers for the users application. You have written unit tests with your favorite testing libraries. You want to commit this change before making any more changes to your code base. Because we are talking about tags and meaningful commit messages, you will write your commit message as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;test: Write tests for users POST route


      - Write test cases to test input validators, response status code
        and response body of users POST route
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That simple! Tests are the most obvious and straightforward type of changes that you won't ever need to scratch your head to classify correctly.&lt;/p&gt;

&lt;p&gt;You might think that the &lt;code&gt;test&lt;/code&gt; tag is only usable for changes that involve writing unit tests. You may right, but what do you think about the following?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creating mocks for classes, methods, functions, API endpoints, and data&lt;/li&gt;
&lt;li&gt;Adding end-to-end tests that emulate real user scenarios&lt;/li&gt;
&lt;li&gt;Refactoring and organizing testing code to improve maintainability&lt;/li&gt;
&lt;li&gt;Creating a custom testing library by encapsulating the functionalities of a testing library&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  6. The &lt;code&gt;chore&lt;/code&gt; tag
&lt;/h3&gt;

&lt;p&gt;Just like it sounds, a &lt;code&gt;chore&lt;/code&gt; is a change that keeps your project environment in order. These changes are not refactors - because they don't touch any lines of code, they are not fixes - because they don't resolve issues or bugs -  and they do not introduce new features to the system. The &lt;code&gt;chore&lt;/code&gt; changes are necessary for maintaining and improving the project in ways that do not affect the experience of the end user.&lt;/p&gt;

&lt;p&gt;Now what kind of change do you suppose we can classify as a chore? Let's say you have been building and improving your project to the point that you have some files that you no longer use for the functionalities in your system. This could be a class file that you have replaced with a third-party library or UI components that you don't use anymore. The best thing to do about these files is to delete them. The resulting change of deleting an unused file does not affect the functionality or the codebase of your system but it does keep things clean in your project. This is the kind of change that you classify as a &lt;code&gt;chore&lt;/code&gt;. If you were to write a commit message, it would look more or less like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chore: Remove unused files

      - Delete the files for the ABC class and xyz components that are
        no longer used in the system
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;chore&lt;/code&gt; changes are not limited to removing unused files, they may also include things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Containerizing your project by adding a Dockerfile&lt;/li&gt;
&lt;li&gt;Updating README.md&lt;/li&gt;
&lt;li&gt;Adding npm scripts to the package.json file&lt;/li&gt;
&lt;li&gt;Installing dependencies and development dependencies&lt;/li&gt;
&lt;li&gt;Configuring testing environment&lt;/li&gt;
&lt;li&gt;Configuring development tools&lt;/li&gt;
&lt;li&gt;Updating existing modules or packages.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's not all about the &lt;code&gt;chore&lt;/code&gt; tag but it's enough to give you an idea of what it's all about. Let's see what next.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. The &lt;code&gt;revert&lt;/code&gt; tag
&lt;/h3&gt;

&lt;p&gt;The revert tag is used when you do a &lt;code&gt;git revert&lt;/code&gt;, that is when you undo a change that had been committed so that your code base can look like nothing happened at all. A revert is not a kind of change that should leave you wondering about what just happened because you won't see it anywhere. A revert is a change that erases evidence of what was done before. Therefore it is very important that you tag all reversed changes as &lt;code&gt;revert&lt;/code&gt; because unlike &lt;code&gt;git reset&lt;/code&gt;, a revert does not leave unstaged changes in the working area.&lt;/p&gt;

&lt;p&gt;Now, under what circumstances would you want to revert a commit? Assume you removed a functionality that allowed users to delete their information from the system. For some reason, you didn't want them to delete their details, at least not directly. You had committed the change as a &lt;code&gt;feat&lt;/code&gt; below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;feat: Disable users from deleting their details from the system
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That went well. After several other changes in the system, you now want users to be able to delete their details directly anyway. You don't want to rewrite the code that you had written in the past so you will simply do a &lt;code&gt;git revert&lt;/code&gt;. This is when you use the &lt;code&gt;revert&lt;/code&gt; tag on a commit message. In my experience revert messages tag and commit themselves but in case you are curious to see what it would look like, be my guest:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;revert: Revert "feat: Disable users from deleting their details from 
        the system"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just like any other kind of change, a revert can be done under several circumstances including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The need to maintain integrity in the commit history. This is for teams that prefer to undo changes via a revert over a reset. They want to keep records of all changes including the ones you want to remove.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Undoing changes after they have been deployed. Assume you introduced a feature but it is misbehaving in production. The safest way to deal with it is to revert the change so you can work on a better implementation while the buggy feature is off the production code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Undoing a mistaken commit, for example, you accidentally deleted important files from the project, committed the change and now you want them back.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That covers the revert tag, let's see about the &lt;code&gt;docs&lt;/code&gt; tag.&lt;/p&gt;

&lt;h3&gt;
  
  
  8. The &lt;code&gt;docs&lt;/code&gt; tag
&lt;/h3&gt;

&lt;p&gt;A change is classified as &lt;code&gt;docs&lt;/code&gt; if it involves writing or removing plain texts on a markdown file or on codebase as comments or docstrings. All changes to code documentation are considered docs including updating the content of the README file. &lt;/p&gt;

&lt;p&gt;Let's say you have been working on a project on your own for some time. You want to invite a few team members to join you in the development. Inviting new members will require you to write some instructions on how to set up the project locally for their sake. You will write the instructions in the README.md or any other markdown file. Once you are done, you will commit the change with a message that looks more or less like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docs: Create instructions for setting up the project locally
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Other changes where the &lt;code&gt;docs&lt;/code&gt; tag is appropriate are :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creating or updating a client or developer documentation&lt;/li&gt;
&lt;li&gt;Adding or removing comments in a codebase&lt;/li&gt;
&lt;li&gt;Updating or creating user manuals&lt;/li&gt;
&lt;li&gt;Adding docstrings to a codebase&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The list is surely longer than we can cover today. The bottom line is, that the &lt;code&gt;docs&lt;/code&gt; tag is used when the change you are committing means that you are communicating something in plain words. This includes all cases where you are altering information from existing documentation.&lt;/p&gt;

&lt;h3&gt;
  
  
  9. The &lt;code&gt;style&lt;/code&gt; tag
&lt;/h3&gt;

&lt;p&gt;You might think that the &lt;code&gt;style&lt;/code&gt; tag is used when you add style to user interfaces but that's very far from the truth. The style tag is used when you make a change that does not affect the logic or semantics of the code but affects the arrangement of the lines of code. These are changes related to the indentation of code, the amount of whitespace between lines of code, the position of curly braces in control structures of functions, whether you used curly braces to enclose one line of code in an else block, etc. The petty things that affect how your code visually looks are committed as &lt;code&gt;style&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Assume you initially had a habit of writing very long lines of code without breaking into the next line. After reading the book &lt;em&gt;Clean Code&lt;/em&gt; by Uncle Bob, you decide to make your code a little cleaner by breaking the lines to be shorter. This is not a refactor because you did not change any characters in the code. This is a &lt;code&gt;style&lt;/code&gt; which can be committed as follows&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;style: Reformat code

      - Break long lines of code into shorter lines
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The other changes that can be committed as &lt;code&gt;style&lt;/code&gt; include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Removing or adding whitespaces in the code file&lt;/li&gt;
&lt;li&gt;Renaming variables and functions for the sake of conventional consistency&lt;/li&gt;
&lt;li&gt;Reformatting comments and docstrings to improve readability&lt;/li&gt;
&lt;li&gt;Aligning and indenting code within blocks for visual clarity&lt;/li&gt;
&lt;li&gt;Rearranging methods in a class or function in a file&lt;/li&gt;
&lt;li&gt;Altering the order of imports&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's enough to give you an idea of what kind of changes can be tagged as &lt;code&gt;style&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The tags we have discussed above are not all that exists in the software engineering world but they are enough for a beginner to intermediate developer. The list grows longer as you get more experience as a developer. These tags are not hard rules in version control systems but a good practice in writing meaningful commit messages. They may not make a lot of sense now but the more you use them, the more you will appreciate them. Use these tags and more that you will learn along the way and you will always be proud of the commit messages you write.&lt;/p&gt;

</description>
      <category>git</category>
    </item>
    <item>
      <title>Handling Bad JSON Input Error in Express app</title>
      <dc:creator>Felix Owino</dc:creator>
      <pubDate>Fri, 02 Aug 2024 15:00:48 +0000</pubDate>
      <link>https://forem.com/ghostaram/handling-bad-json-input-error-in-express-app-4go8</link>
      <guid>https://forem.com/ghostaram/handling-bad-json-input-error-in-express-app-4go8</guid>
      <description>&lt;p&gt;Have you ever experienced this error before or are you experiencing it now? I'll be honest and say I experienced it more than once but I didn't care so much at first. This error is normally thrown by the express body-parser as a syntax error. If you have a global error handler in your app, the error will always be sent to the user as an internal server error with status code 500. But you have a problem with that, don't you? Yes, so do I. &lt;/p&gt;

&lt;p&gt;Why do we have a problem if it will be handled anyway? Well, the problem with this problem being sent as an internal server error is that it's not originating from our side. The error of bad JSON format is caused by bad JSON data, something like a trailing comma in a JSON object. &lt;/p&gt;

&lt;p&gt;You see, that error is thrown because of a client mistake. The error is triggered by something from the client side. We want the client to know that they did something wrong. We don't want the client to get furious at us because of a problem they are responsible for, that's what happens when we respond with status code 500 for all errors. This error is a special one, caused by a bad input format from the client. We want to send status code 400 instead.&lt;/p&gt;

&lt;p&gt;The error caused by bad JSON format is thrown by the body parser but we can't put the body parser in a try-catch block and do what we want with the error. We will let the body parser forward the error to the global error handler then we handle it there.&lt;/p&gt;

&lt;p&gt;We know it is a &lt;code&gt;SyntaxError&lt;/code&gt;, that's what we will be looking for. We also know that the message will say something about JSON. We use the type of the error and the error message to narrow down our action as done below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const handleServerErrors = ( 
        err:Error, req: Request, res: Response, next: NextFunction) =&amp;gt;{
            if(err){
                if (err instanceof SyntaxError){

                    if(/JSON/i.test(err.message)){

                        res.status(400).json("Bad JSON format")

                    } else{
                        res.status(500).json(err.message)
                    }
                    console.log(err.message)

                } else{
                    res.status(500).json('Unexpected server error.')

                    console.log(`Name ${err.name}, 
                     Message:${err.message}`)

                    console.log(`Error Stack \n ${err.stack}`)
                }
          }
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we pass the above error handler to the express app as the last middleware in the system. If the client sends data in bad JSON format, we will respond with status code 400 and a message informing them about the problem in the response body.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Creating A Carousel with Vanilla JS</title>
      <dc:creator>Felix Owino</dc:creator>
      <pubDate>Fri, 19 Jul 2024 10:43:45 +0000</pubDate>
      <link>https://forem.com/ghostaram/creating-a-carousel-with-vanilla-js-3f82</link>
      <guid>https://forem.com/ghostaram/creating-a-carousel-with-vanilla-js-3f82</guid>
      <description>&lt;p&gt;In the real world, a carousel refers to a series of structures mounted on a circular platform that rotates around a central axis. Examples of carousels in the real world are things like merry-go-round and carousel rides. In the context of user interfaces, carousels are a series of items such as images, videos, files, or texts designed to be viewed one item at a time within a specific container on the screen in a linear sequence. Users can navigate through the items in the carousel by clicking its navigation buttons. Carousels can also be automated to self-navigate at specified intervals. In this article, we will learn how to create a carousel on a webpage using HTML, CSS, and vanilla JavaScript.&lt;/p&gt;

&lt;p&gt;Carousels are interesting to view on user interfaces but implementing them is usually a little elusive to beginners. However, it's surprisingly simple to implement once you make sense of what parts of the carousel actually move. &lt;/p&gt;

&lt;p&gt;In most cases, for example, an image carousel, we tend to imagine that the carousel is about the motion of the individual images. That assumption looks true from the viewer's point of view but very inaccurate from the engineering point of view. The truth is, that the motion is never about the individual images but the parent container of the images. &lt;/p&gt;

&lt;p&gt;All the images in a carousel are children of one &lt;code&gt;div&lt;/code&gt; container spread in a horizontal manner. The whole container moves with all its children but only one image is displayed within the viewing container. The other images remain hidden on either side of the viewing container. The viewing container? Yes, you heard me right. Does that mean we have another container apart from the one containing the images? Yes, this container gets to decide how big the displayed image will be and hides everything that does not fit within its borders.&lt;/p&gt;

&lt;p&gt;Enough with the words, let us get practical. We will cover this activity in the following sections:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Structuring the carousel&lt;/li&gt;
&lt;li&gt;Styling the Carousel&lt;/li&gt;
&lt;li&gt;Getting the Carousel in Motion

&lt;ul&gt;
&lt;li&gt;3.1 Viewing the next image&lt;/li&gt;
&lt;li&gt;3.2 Viewing the previous image&lt;/li&gt;
&lt;li&gt;3.3 How the Translation works&lt;/li&gt;
&lt;li&gt;3.4 Automating the rotation&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Adding Indicators&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We will start writing the HTML structure of the carousel.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Structuring the Carousel
&lt;/h3&gt;

&lt;p&gt;We will use image files for this carousel. I downloaded my images. You can find sample images from &lt;a href="https://unsplash.com/" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt; and download or copy their links for your practice. Below is the HTML code:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; &amp;lt;div class="viewing-container"&amp;gt;
        &amp;lt;div class="carousel"&amp;gt;
            &amp;lt;img src="./beautiful-home-1.avif" alt="beautiful home 1"&amp;gt;
            &amp;lt;img src="/beautiful-home-2.avif" alt="beautiful home 2"&amp;gt;
            &amp;lt;img src="./beautiful-home-3.avif" alt="beautiful home 3"&amp;gt;
            &amp;lt;img src="./beautiful-home-5.avif" alt="beautiful home 4"&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;button class="prev"&amp;gt;
            &amp;lt;i class="fa-solid fa-angle-left"&amp;gt;&amp;lt;/i&amp;gt;
        &amp;lt;/button&amp;gt;
        &amp;lt;button class="next"&amp;gt;
            &amp;lt;i class="fa-solid fa-angle-right"&amp;gt;&amp;lt;/i&amp;gt;
        &amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The code snippet above renders the following components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A viewing container that parents the carousel and the navigation buttons&lt;/li&gt;
&lt;li&gt;The carousel container which contains four image files&lt;/li&gt;
&lt;li&gt;Four image elements that render four image files&lt;/li&gt;
&lt;li&gt;A previous navigation button with an icon (left angular brace)&lt;/li&gt;
&lt;li&gt;A next navigation button with an icon (right angular brace)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We are using &lt;a href="https://fontawesome.com/icons" rel="noopener noreferrer"&gt;Font awesome icons&lt;/a&gt; for the angular braces. Font Awesome icons require an external stylesheet to work. Go to &lt;a href="https://cdnjs.com/libraries/font-awesome" rel="noopener noreferrer"&gt;cdnjs font awesome library&lt;/a&gt; and copy the link tag to the stylesheet (marked with this icon - &amp;lt;/&amp;gt;). You will find a long list of links, the first link on the list should work.  Paste the link within the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; of your HTML file. The &lt;code&gt;head&lt;/code&gt; of your HTML file should resemble the one below. The Font Awesome link doesn't have to be an exact match because it is subject to change.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;head&amp;gt;
    &amp;lt;meta charset="UTF-8"&amp;gt;
    &amp;lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&amp;gt;
    &amp;lt;link rel="stylesheet" href="./style.css"&amp;gt;

    &amp;lt;!-- Font Awesome Stylesheet --&amp;gt;
    &amp;lt;link rel="stylesheet" 
        href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.6.0/css/all.min.css" 
        integrity="sha512-Kc323vGBEqzTmouAECnVceyQqyqdsSiqLQISBL29aUW4U/M7pSPA/gEUZQqv1cwx4OnYxTxve5UMg5GT6L4JJg==" 
        crossorigin="anonymous" referrerpolicy="no-referrer" /&amp;gt;

    &amp;lt;title&amp;gt;Carousel&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;That is all the HTML we need for now, let us add some basic styles to the carousel.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Styling the Carousel
&lt;/h3&gt;

&lt;p&gt;The following code snippet contains a few basic styles for the carousel:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;body{
    padding-block-start: 4rem;
}

.carousel{
    display: flex;
}

.viewing-container{
    width: 25%;
    position: relative;
    border: solid 3px red;
}

.carousel img{
    width: 100%;
}

button{
    position: absolute;
    top: 50%;
    padding: .4rem .8rem;
    border:  none;
    background-color: rgba(0, 0, 0, 0.5);
    color: white;
    font-size: 1.5rem;
}

button.next{
    right: 1rem;
}

button.prev{
    left: 1rem;
} 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;See the result of the styles in the screenshot below then let me explain just what we have done.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F8b4vy73tkpd942fctnwu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F8b4vy73tkpd942fctnwu.png" alt="carousel images"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Using the CSS styles above, we have done the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We have horizontally spread the images in the carousel container using flex&lt;/li&gt;
&lt;li&gt;We have intentionally set the width of the viewing container to 25% to allow us to see all the images within the screen. If you have more than 4 images, 25% width won't have the same effect.&lt;/li&gt;
&lt;li&gt;We have set the position property of the viewing container to relative to allow us to position the navigation buttons on it.&lt;/li&gt;
&lt;li&gt;We have intentionally added a red solid border around the viewing container to distinguish it from the rest of the screen.&lt;/li&gt;
&lt;li&gt;We have set every image to be 100% as wide as the viewing container.&lt;/li&gt;
&lt;li&gt;We have set the positions of the buttons as absolute, vertically centered, and 1 rem from the edges of the viewing container.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We have intentionally left the styling unfinished (with overflow) so that you can see that creating a carousel begins by spreading all the images horizontally. We would also choose to do it vertically but we want to create a horizontal carousel. Before we finish the styling, we will get the carousel in motion using JavaScript.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Getting the Carousel in Motion
&lt;/h2&gt;

&lt;p&gt;There are two ways to make a carousel go around. You can use the navigation buttons or make the carousel rotate automatically in specified intervals. We will implement both approaches starting with the navigation buttons.&lt;/p&gt;

&lt;p&gt;There are two navigation buttons on the carousel viewing container: a previous button and a next button. If we want to see the images to the right, we will click the next button (the button to the right of the viewing container). Likewise, to view the images to the left of the viewing container, we click the previous button (the button to the left of the container). &lt;/p&gt;

&lt;p&gt;Let's explore how we can program the carousel to enable viewing images on the right side of the container.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.1 Viewing the next Image.
&lt;/h3&gt;

&lt;p&gt;As you click the &lt;code&gt;next&lt;/code&gt; button, you expect the image on the right side of the viewing container to be moved inside the viewing container. Let's implement that in the code snippet below:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const carousel = document.querySelector('.carousel');
const nextButton = document.querySelector('.next');

const carouselLength = document.querySelectorAll(
       '.carousel img').length;

let currentPositon = 0

nextButton.addEventListener('click', () =&amp;gt; {
    currentPositon = currentPositon &amp;lt; carouselLength - 1 ? currentPositon + 1 : 0

    const offset = -100 * currentPositon
    carousel.style.transform = `translateX(${offset}%)`
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Confused? Don't worry, you will understand what's going on in no time.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First, we get the carousel container, the &lt;code&gt;div&lt;/code&gt; element that parents all the images.&lt;/li&gt;
&lt;li&gt;Secondly, we get the &lt;code&gt;next&lt;/code&gt; button, which is the button to the right of the viewing container.&lt;/li&gt;
&lt;li&gt;Then we get the length of the carousel. This is equal to the number of images in the carousel. We get the length of the &lt;code&gt;NodeList&lt;/code&gt; of all images in the carousel. The &lt;code&gt;NodeList&lt;/code&gt; and all its contents are totally useless to us except its length. &lt;/li&gt;
&lt;li&gt;We initialize our starting position to 0. This is where we are before the carousel begins to move. The current position represents the index (in &lt;code&gt;NodeList&lt;/code&gt;) of the image displayed within the viewing container.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's all for the variables, let's talk about the &lt;code&gt;click&lt;/code&gt; event handler. &lt;/p&gt;

&lt;p&gt;Here, we adjust the value of &lt;code&gt;currentPosition&lt;/code&gt; by 1 to point to the next image in the carousel. &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;currentPositon = currentPositon &amp;lt; carouselLength - 1 ? currentPositon + 1 : 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Take note that we do this conditionally, we only increment the position up to the time when it points to the last image in the carousel, and then we go back to 0. If we still want to view the next image after the last, we are returned back to where we started. Without the conditional checks, we will continue to view empty spaces.&lt;/p&gt;

&lt;p&gt;The interesting part is saved for last, &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    const offset = -100 * currentPositon
    carousel.style.transform = `translateX(${offset}%)`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;we translate the carousel leftwards in relation to the value of the &lt;code&gt;currentPosition&lt;/code&gt;. We negate the &lt;code&gt;offset&lt;/code&gt; (translation distance) because we want the carousel to move leftwards. We multiply the &lt;code&gt;currentPosition&lt;/code&gt; by 100 to calculate the offset as a percentage-based translation, ensuring that each item in the carousel is translated by its full width. Think about it as swiping left to see what's on the right. &lt;/p&gt;

&lt;p&gt;Save your work and try clicking the &lt;code&gt;next&lt;/code&gt; button to see for yourself how the carousel container moves to show you the next image.&lt;/p&gt;

&lt;p&gt;You must have realized how rough and sudden the motion of the carousel is. It's not as gradual and smooth as you expect. Let's fix that by customizing the transition of the carousel using CSS.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.carousel{
    display: flex;
    transition-property: all;
    transition-duration: 2s;
    transition-delay: 0;
    transition-timing-function: ease;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Update the styles in the carousel class with the above properties and values and see how smooth and gradual the motion gets. &lt;/p&gt;

&lt;p&gt;We are done with the next button. Let us make the previous button work just as well if not better.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.2 Viewing the previous Image.
&lt;/h3&gt;

&lt;p&gt;Calculating the position for the previous image takes the direct opposite of the calculation we performed when viewing the next image. We decrement the value of the current position until the value becomes 0. Once it reaches 0, instead of decrementing to -1, the &lt;code&gt;currentPosition&lt;/code&gt; will be reinitialized to the last position in the carousel. If the value of &lt;code&gt;currentPosition&lt;/code&gt; is zero, pressing the previous button will take you to the last image in the carousel, the end. The following code snippet extends the previous scripts:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const prevButton = document.querySelector('.prev');

prevButton.addEventListener('click', () =&amp;gt;{
    currentPositon = currentPositon &amp;gt; 0 ? currentPositon - 1 : carouselLength - 1

    const offset = -100 * currentPositon
    carousel.style.transform = `translateX(${offset}%)`
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This is similar to swiping right to see what's on the left.&lt;/p&gt;

&lt;p&gt;Have you noticed that we are still negating the &lt;code&gt;offset&lt;/code&gt; even though we want the carousel to move rightwards? Why aren't we making it a positive translation here? Why is the calculation the same as what we did in the previous section but the effect looks like the opposite? You will understand what's happening shortly, but first, let's make the JavaScript code a little cleaner.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const carousel = document.querySelector('.carousel');
const prevButton = document.querySelector('.prev');
const nextButton = document.querySelector('.next');

const carouselLength = document.querySelectorAll('.carousel img').length;

let currentPositon = 0

const showImage = (currentPositon) =&amp;gt;{
    const offset = -100 * currentPositon
    carousel.style.transform = `translateX(${offset}%)`
}

nextButton.addEventListener('click', () =&amp;gt; {
    currentPositon = currentPositon &amp;lt; carouselLength - 1 ? currentPositon + 1 : 0
    showImage(currentPositon)
})

prevButton.addEventListener('click', () =&amp;gt;{
    currentPositon = currentPositon &amp;gt; 0 ? currentPositon - 1 : carouselLength - 1
    showImage(currentPositon)
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The code snippet above achieves the same goal with fewer lines of code in the &lt;code&gt;click&lt;/code&gt; event handlers. We have refactored the code by encapsulating the translation and offset calculation in a reusable function, &lt;code&gt;showImage&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Now let's learn why we are always doing a negative translation when it looks like we are changing directions.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.3 How The Translation Works
&lt;/h3&gt;

&lt;p&gt;In practice, the translation distance and the translation direction of an element are always calculated relative to its origin, the initial position of the element without any translation. &lt;/p&gt;

&lt;p&gt;If the intended translation destination of an element lies to the right of the element before any translation, its translation direction will always be positive regardless of what it looks like in the display. Likewise, the translation direction of an element will always be negative if the translation destination lies to the left of its translation origin.&lt;/p&gt;

&lt;p&gt;In our case, all the images in the carousel before translation are always on the right-hand side of the viewing container. It does not matter whether, from the look of things the images are to the left or right side of the viewing container, the computer will always reset to the original positions (right-hand side of the viewing container) before executing a translation. &lt;/p&gt;

&lt;p&gt;Assume you want to see the image at position 4 in the carousel, the translation direction and translation distance will always be negative and 400% (-400%) respectively. The offset will always be -400% whether you are clicking the previous button or the next button. &lt;/p&gt;

&lt;p&gt;I hope that helped clear your doubts if you had any. Now let's wind up by centering the viewing container, increasing its width, removing the border, and hiding the images that lie outside the viewing container using the following CSS rules:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.viewing-container{ 
    /*Remove the border*/
    position: relative;
    width: 50%; /* Increase from 25 to 50*/
    overflow: hidden; /*Hide overflow*/
    margin: auto; /*Center the container*/
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The screenshot below shows the centered, enlarged, and borderless viewing container without overflows:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fstbitpo3eu78sqsu05bl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fstbitpo3eu78sqsu05bl.png" alt="Centered Carousel"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3.4 Automating the rotation.
&lt;/h2&gt;

&lt;p&gt;Remember we did say earlier that the motion of the carousel can be automated. We can use the &lt;code&gt;setInterval&lt;/code&gt; function to calculate the &lt;code&gt;currentPosition&lt;/code&gt; and translate the carousel after specific intervals. The code snippet below implements the automation of a carousel to rotate after every 5 seconds.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;setInterval(() =&amp;gt;{
    currentPositon = currentPositon &amp;lt; carouselLength -1 ? currentPositon + 1 : 0
    showImage(currentPositon)
}, 5000)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;There is one problem you will experience by including this automation. There seems to be an interruption when you want to control the motion with the navigation buttons. To fix that problem, you can store the value returned by the &lt;code&gt;setInterval&lt;/code&gt; function and use it to clear the intervals once a button is clicked. The code snippet below shows the complete code snippet with the fixes.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// // script.js
const prevButton = document.querySelector('.prev');
const carousel = document.querySelector('.carousel');
const carouselLength = document.querySelectorAll('.carousel img').length;
const nextButton = document.querySelector('.next');

let currentPositon = 0

const showImage = (currentPositon) =&amp;gt;{
    const offset = -100 * currentPositon
    carousel.style.transform = `translateX(${offset}%)`
}

const interval = setInterval(() =&amp;gt;{
    currentPositon = currentPositon &amp;lt; carouselLength -1 ? currentPositon + 1 : 0

    showImage(currentPositon)
}, 5000)

nextButton.addEventListener('click', () =&amp;gt; {
    clearInterval(interval)

    currentPositon = currentPositon &amp;lt; carouselLength - 1 ? currentPositon + 1 : 0

    showImage(currentPositon)
})

prevButton.addEventListener('click', () =&amp;gt;{
    clearInterval(interval)

    currentPositon = currentPositon &amp;gt; 0 ? currentPositon - 1 : carouselLength - 1

    showImage(currentPositon)
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;With the latest adjustments, the carousel will autorotate only until you click either of the navigation buttons. Once the manual navigation takes over, the automated navigation will stop until the page reloads.&lt;/p&gt;

&lt;h2&gt;
  
  
  4 Adding Indicators
&lt;/h2&gt;

&lt;p&gt;Indicators in a carousel help users know the number of images they have viewed and the ones they haven't viewed. We will create four circular dots at the bottom of the viewing container to act as indicators. We can create circles by adding 4 div elements to the markup. We can use CSS to set their height, width, border, and border radius to make them circular.&lt;/p&gt;

&lt;p&gt;We will extend the viewing container with more elements as in the code snippet below.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    &amp;lt;div class="viewing-container"&amp;gt;
//Initial content - carousel container and buttons
// go here
        &amp;lt;div class="indicators"&amp;gt;
            &amp;lt;div class="indicator"&amp;gt;&amp;lt;/div&amp;gt;
            &amp;lt;div class="indicator"&amp;gt;&amp;lt;/div&amp;gt;
            &amp;lt;div class="indicator"&amp;gt;&amp;lt;/div&amp;gt;
            &amp;lt;div class="indicator"&amp;gt;&amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The following CSS styles will make the &lt;code&gt;div&lt;/code&gt; elements look just like we want.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.indicators{
    display: flex;
    align-items: center;
    justify-content: center;
    gap: .8rem;
    position: absolute;
    bottom: 1rem;
    width: 100%;
}

.indicator{
    width: 8px;
    height: 8px;
    border: solid 1px white;
    border-radius: 50%;
    transition: background-color 2s ease;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;After adding the markup and applying the styles, you should have a series of indicators that resemble the ones shown in the screenshot below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F2bey7wt1m691l2n1yj37.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F2bey7wt1m691l2n1yj37.png" alt="Carousel indicators"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice the four circular dots at the bottom of the screen.&lt;/p&gt;

&lt;p&gt;Having successfully rendered and styled indicators, let us now make them do what they are supposed to do. We will get all the indicators from the DOM and create a function that changes the background color of the dots as the carousel moves. The following code snippet implements the actions described.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const indicators = document.querySelectorAll('.indicator')

const moveIndicator = (currentPositon) =&amp;gt;{
    indicators.forEach((indicator, index) =&amp;gt;{
        indicator.style.backgroundColor = currentPositon === index ? 
            'white': 'rgba(0,0,0,0.5)'
    })
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In the code snippet above, we get all the indicators in a &lt;code&gt;NodeList&lt;/code&gt; and create a function called &lt;code&gt;moveIndicator&lt;/code&gt;. The function accepts the &lt;code&gt;currentPosition&lt;/code&gt; as an argument, and iterates over the &lt;code&gt;NodeList&lt;/code&gt; comparing the &lt;code&gt;currentPosition&lt;/code&gt; with the &lt;code&gt;index&lt;/code&gt; value of every indicator in the list. If the &lt;code&gt;currentPosition&lt;/code&gt; equals the &lt;code&gt;index&lt;/code&gt;, we set the background color to white, otherwise, we set it to a semi-transparent black color.&lt;/p&gt;

&lt;p&gt;We have to call the function every time the carousel moves to update the indicator. Below is the final code snippet with the indicator working as expected.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// // script.js
const prevButton = document.querySelector('.prev');
const carousel = document.querySelector('.carousel');
const carouselLength = document.querySelectorAll('.carousel img').length;
const nextButton = document.querySelector('.next');
const indicators = document.querySelectorAll('.indicator')

let currentPositon = 0

const showImage = (currentPositon) =&amp;gt;{
    const offset = -100 * currentPositon
    carousel.style.transform = `translateX(${offset}%)`
}

const moveIndicator = (currentPositon) =&amp;gt;{
    indicators.forEach((indicator, index) =&amp;gt;{
        indicator.style.backgroundColor = currentPositon === index ?
            'white': 'rgba(0,0,0,0.5)'
    })
}

const interval = setInterval(() =&amp;gt;{
    currentPositon = currentPositon &amp;lt; carouselLength -1 ? 
        currentPositon + 1 : 0

    showImage(currentPositon)
    moveIndicator(currentPositon)
}, 5000)

nextButton.addEventListener('click', () =&amp;gt; {
    clearInterval(interval)

    currentPositon = currentPositon &amp;lt; carouselLength - 1 ?
         currentPositon + 1 : 0

    showImage(currentPositon)
    moveIndicator(currentPositon)
})

prevButton.addEventListener('click', () =&amp;gt;{
    clearInterval(interval)

    currentPositon = currentPositon &amp;gt; 0 ? 
        currentPositon - 1 : carouselLength - 1

    showImage(currentPositon)
    moveIndicator(currentPositon)
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The screenshot below indicates that we are currently viewing the second image in the carousel.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fotaioxlthsixghich78z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fotaioxlthsixghich78z.png" alt="Indicating second image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, we are done creating a carousel with vanilla JavaScript (without third-party libraries). Carousels come in handy when you want to display a series of images, videos, documents, or texts within a limited space. Creating a carousel involves horizontally translating the parent container of the images or files that make up the carousel. The translation direction of a carousel will always be the same regardless of the position of the previous translations. The translation distance and translation direction for displaying the same image will always be the same regardless of the direction of navigation. Carousels can be navigated manually or automatically with set intervals. &lt;/p&gt;

&lt;p&gt;Congratulations, now try creating your carousel from what you have learned. Feel free to say something in the comment section. Find out more about &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/translate" rel="noopener noreferrer"&gt;CSS translations&lt;/a&gt; from MDN.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>programming</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Implementing File Input By Copy-Paste on the Web</title>
      <dc:creator>Felix Owino</dc:creator>
      <pubDate>Wed, 17 Jul 2024 11:54:04 +0000</pubDate>
      <link>https://forem.com/ghostaram/implementing-file-input-by-copy-paste-on-the-web-npb</link>
      <guid>https://forem.com/ghostaram/implementing-file-input-by-copy-paste-on-the-web-npb</guid>
      <description>&lt;p&gt;In the sphere of web development, there are multiple ways to upload files when collecting user input. One of the methods is copy-paste. Copy-paste for file input is a very intuitive method of uploading files from users. Copy-paste file input method relieves users of the need to memorize the location of the file they want to upload. In this article, we will discuss how you can implement file input by copy-paste on your website.&lt;/p&gt;

&lt;p&gt;We will implement the copy-paste file input by taking advantage of the &lt;code&gt;ClipboadEvent&lt;/code&gt;  and the &lt;code&gt;EventTarget&lt;/code&gt; interfaces. The &lt;code&gt;ClipboardEvent&lt;/code&gt; interface provides information about the &lt;code&gt;paste&lt;/code&gt; event, and the &lt;code&gt;EventTarget&lt;/code&gt; interface allows us to listen to the paste event.&lt;/p&gt;

&lt;p&gt;While listening to the paste event, we will attach an event handler function where we decide what to do with the pasted items. In our case, we will take the pasted file and render it instantly after it is completely loaded into the browser. We will begin with the HTML and the styles.&lt;/p&gt;

&lt;h2&gt;
  
  
  The HTML and the Styles
&lt;/h2&gt;

&lt;p&gt;Let us start by creating the HTML markup of the paste area. The code snippet below is the HTML markup:&lt;/p&gt;

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

&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang="en"&amp;gt;
&amp;lt;head&amp;gt;
    &amp;lt;meta charset="UTF-8"&amp;gt;
    &amp;lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&amp;gt;
    &amp;lt;title&amp;gt;Copy-Paste File Input&amp;lt;/title&amp;gt;
    &amp;lt;link rel="stylesheet" href="style.css"&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
    &amp;lt;div 
        id="pasteArea" 
        contenteditable="true" 
        style="border: 2px dashed #ccc; padding: 20px;"
    &amp;gt;
        Paste your file here
    &amp;lt;/div&amp;gt;
    &amp;lt;div id="preview"&amp;gt;&amp;lt;/div&amp;gt;
    &amp;lt;script src="script.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;


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

&lt;/div&gt;

&lt;p&gt;The code snippet above renders a rectangular container within which we will be able to paste files. The container has an attribute called &lt;code&gt;contenteditable&lt;/code&gt; set to &lt;code&gt;true&lt;/code&gt;. The &lt;code&gt;contenteditable&lt;/code&gt; attribute is important to enabling the pasting of files or any other items in the container. If the &lt;code&gt;contenteditable&lt;/code&gt; attribute is changed to &lt;code&gt;false&lt;/code&gt; or removed, the &lt;code&gt;paste&lt;/code&gt; action will not work as expected. We also have a container with the id of &lt;code&gt;preview&lt;/code&gt;. We will use the preview container to preview the image pasted by the user.&lt;/p&gt;

&lt;p&gt;Let's add a few basic styles to our markup from &lt;code&gt;style.css&lt;/code&gt;&lt;/p&gt;

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

*{
    font-family: Arial, Helvetica, sans-serif;
}

body{
    text-align: center;
    margin-block-start: 4rem;
}
#pasteArea {
    border: 2px dashed #ccc;
    padding: 20px;
    width: 300px;
    height: 200px;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    cursor: pointer;
    margin: auto;
    color: rgb(5, 89, 89);
}

#preview img {
    max-width: 100%;
    margin-top: 10px;
}


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

&lt;/div&gt;

&lt;p&gt;The above markup and style sheet creates a simple dash-bordered container with a simple prompt text as shown in the screenshot below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fewg9ctw0ls6kbzbwkuco.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fewg9ctw0ls6kbzbwkuco.png" alt="Paste Container"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that we have created the UI, let us add some useful functionalities with JavaScript in the next section.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Script
&lt;/h2&gt;

&lt;p&gt;In this section, we will use JavaScript to add a &lt;code&gt;paste&lt;/code&gt; event listener to the paste area. Before we get the paste area from the DOM to attach the event listener, we first wait for the DOM content to be loaded as in the code snippet below.&lt;/p&gt;

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

document.addEventListener('DOMContentLoaded', () =&amp;gt; {
    const pasteArea = document.querySelector('#pasteArea');

    pasteArea.addEventListener('paste', (event) =&amp;gt; {

    });
});


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

&lt;/div&gt;

&lt;p&gt;In the code snippet above, we have added a listener for the &lt;code&gt;DOMContentLoaded&lt;/code&gt; event. This allows us to wait for the DOM tree to be created before we can get the DOM elements. Next, we select the paste area container and append a &lt;code&gt;paste&lt;/code&gt; event listener to it. &lt;/p&gt;

&lt;h5&gt;
  
  
  Getting the file from the pasted items
&lt;/h5&gt;

&lt;p&gt;The &lt;code&gt;paste&lt;/code&gt; event handler was left unimplemented in the previous code snippet. Let's implement it by getting the data from the event object and logging them in the console. We will do more with the data later in the article, for now, we just want to ensure that the files are received when items are pasted in the paste area. The code snippet below shows the minimal implementation of the &lt;code&gt;paste&lt;/code&gt; event handler.&lt;/p&gt;

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

pasteArea.addEventListener('paste', (event) =&amp;gt; {
        const items = event.clipboardData.items
        for (const item of items) {
            if (item.kind === 'file') {
                const file = item.getAsFile()

                console.log(file)
            }
        }
    })


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

&lt;/div&gt;

&lt;p&gt;In the code snippet above, we get items from the &lt;code&gt;event.clipboardData&lt;/code&gt; object. The &lt;code&gt;event.clipboardData.items&lt;/code&gt; is a &lt;code&gt;DataTransferItemList&lt;/code&gt; which is a list-like object containing the content of the pasted items. The items are stored in a list because it is possible for a user to copy and paste multiple items at once. &lt;/p&gt;

&lt;p&gt;Next, we iterate over the items using the &lt;code&gt;for ...of&lt;/code&gt; loop. In the loop, we check if each of the items is a file. If the item is of king 'file', we get it as a file and print it on the browser's console.&lt;/p&gt;

&lt;p&gt;Printing the file information on the console is not very useful to the users of your web page. Let's do something a little more interesting in the next section.&lt;/p&gt;

&lt;h5&gt;
  
  
  Previewing the uploaded file
&lt;/h5&gt;

&lt;p&gt;It would be hard for a user to know that the file upload was successful after pasting the items for the clipboard if we don't show it anywhere. It is important to indicate that the file was successfully uploaded by displaying something that indicates success. What better way to indicate the success of an upload than displaying the uploaded file itself? &lt;/p&gt;

&lt;p&gt;In this section, we will extend the &lt;code&gt;paste&lt;/code&gt; event handler to create a URL from the received file. We will use the created URL to render the file once it's loaded into the browser. We will take advantage of the &lt;code&gt;FileReader&lt;/code&gt; API to create a URL from the file as coded in the snippet below.&lt;/p&gt;

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

pasteArea.addEventListener('paste', (event) =&amp;gt; {
        const items = event.clipboardData.items
        for (const item of items) {
            if (item.kind === 'file') {
                const file = item.getAsFile()


                const reader = new FileReader();

                reader.onloadend = (e) =&amp;gt; {
                    const url = e.target.result
                    console.log(url)

                };
                reader.readAsDataURL(file);
            }
        }
    });


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

&lt;/div&gt;

&lt;p&gt;In the code snippet above, we have created an instance of the &lt;code&gt;FileReader&lt;/code&gt; and used it to generate the data URL. We have also appended a &lt;code&gt;loadend&lt;/code&gt; event listener to the &lt;code&gt;FileReader&lt;/code&gt; object where we log the the result of the reading to the console. This is the first step towards previewing the file, we can now use the URL to display the file.&lt;/p&gt;

&lt;p&gt;Assuming the user pasted image files, the following code snippet shows how we can extend the event handler to create a URL and display the image file.&lt;/p&gt;

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

 reader.onloadend = (e) =&amp;gt; {
       const url = e.target.result
       const preview = document.querySelector('#preview')
       const img = document.createElement('img');

       img.src = url;
       preview.appendChild(img);
   };


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

&lt;/div&gt;

&lt;p&gt;In the code snippet above, we get the preview container from the DOM and create an &lt;code&gt;img&lt;/code&gt; element for rendering the image. We assign the created URL as the &lt;code&gt;src&lt;/code&gt; of the image and append the image to the preview container. Once the image is appended to the preview container, the user can now know that the image they pasted was successfully loaded into the web page.&lt;/p&gt;

&lt;p&gt;Success! We have successfully implemented file uploads by copy-paste on a webpage. This method of file upload gives users the privilege of uploading files easily without the need to click several buttons to select the file to be uploaded. The &lt;code&gt;ClipboadEvent&lt;/code&gt; interface provides an easy way to collect data from items pasted on the browser. The &lt;code&gt;FileReader&lt;/code&gt; interface allows us to create a URL from the uploaded file and use it to preview the uploaded file. &lt;/p&gt;

&lt;p&gt;Feel free to say something in the comment section. Find more about the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/ClipboardEvent/clipboardData" rel="noopener noreferrer"&gt;ClipBoardEvent&lt;/a&gt; and the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/FileReader" rel="noopener noreferrer"&gt;FileReader&lt;/a&gt; interfaces from MDN.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>frontend</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Implementing Drag-Drop for File Input on the Web.</title>
      <dc:creator>Felix Owino</dc:creator>
      <pubDate>Tue, 16 Jul 2024 12:17:54 +0000</pubDate>
      <link>https://forem.com/ghostaram/implementing-drag-drop-for-file-input-on-the-web-6c</link>
      <guid>https://forem.com/ghostaram/implementing-drag-drop-for-file-input-on-the-web-6c</guid>
      <description>&lt;p&gt;Drag-drop is one of the most engaging ways of transferring files between windows on a computer. All modern file explorers come with this functionality. Browsers also happen to have a default behavior to drag-drop. By default, the browser will try to open a file dropped into it unless it is programmed to do something else. In this article, we will learn how to program the browser to treat a drag-drop as a file input operation. We will also extend the program to allow us to open the file input dialog and select a file by clicking the drop-drop target.&lt;/p&gt;

&lt;p&gt;Implementing actions during drag-drop can be done using the &lt;code&gt;DragEvent&lt;/code&gt; interface provided in the browser by JavaScript. The &lt;code&gt;DragEvent&lt;/code&gt; interface provides several events from when a drag begins to when it ends. In this article, we will leverage the power of the &lt;code&gt;DragEvent&lt;/code&gt; interface to create a drag-drop file input user interface. &lt;/p&gt;

&lt;p&gt;We will implement the proposed user interface in the following order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create the HTML Markup&lt;/li&gt;
&lt;li&gt;Style the Markup&lt;/li&gt;
&lt;li&gt;Make it interactive&lt;/li&gt;
&lt;li&gt;Style the interaction&lt;/li&gt;
&lt;li&gt;Make it clickable&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's begin ...&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Create the HTML Markup
&lt;/h2&gt;

&lt;p&gt;Before going any further into the article, let us create a simple HTML markup.&lt;/p&gt;

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

index.html

&amp;lt;body&amp;gt;
    &amp;lt;!DOCTYPE html&amp;gt;
    &amp;lt;html lang="en"&amp;gt;
    &amp;lt;head&amp;gt;
      &amp;lt;meta charset="UTF-8"&amp;gt;
      &amp;lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&amp;gt;
      &amp;lt;title&amp;gt;Drag and Drop File Upload&amp;lt;/title&amp;gt;
      &amp;lt;link rel="stylesheet" href="./style.css"&amp;gt;
    &amp;lt;/head&amp;gt;
    &amp;lt;body&amp;gt;
      &amp;lt;div id="drop-zone" class="drop-zone"&amp;gt;
        &amp;lt;p&amp;gt;Drag &amp;amp; drop files here or click to upload&amp;lt;/p&amp;gt;
      &amp;lt;/div&amp;gt;
      &amp;lt;script src="./drag-drop.js"&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;/body&amp;gt;
    &amp;lt;/html&amp;gt;

&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;


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

&lt;/div&gt;
&lt;h2&gt;
  
  
  2. Style the Markup
&lt;/h2&gt;

&lt;p&gt;The following stylesheet provides a few basic styles for the page.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

style.css

body {
    font-family: Arial, sans-serif;
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    margin: 0;
    background-color: #f0f0f0;
  }

  .drop-zone {
    width: 300px;
    height: 200px;
    border: 2px dashed #007bff;
    border-radius: 4px;
    display: flex;
    justify-content: center;
    align-items: center;
    text-align: center;
    color: #007bff;
    cursor: pointer;
    transition: background-color 0.2s ease;
  }


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

&lt;/div&gt;

&lt;p&gt;The above markup and style create a container with a blue dotted border and prompt text. The screenshot below shows what we have just created when opened in the browser.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F0av6o8d8nhgu1lo0rlik.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F0av6o8d8nhgu1lo0rlik.png" alt="The Drop zone container"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Make it interactive
&lt;/h2&gt;

&lt;p&gt;Dragging and dropping files into the dotted container or clicking it to input files won't work just yet. We need JavaScript for that part. In the script, we will add various event listeners to elements in the document. The first event we will listen for is the &lt;code&gt;DOMContentLoaded&lt;/code&gt; event on the &lt;code&gt;document&lt;/code&gt;. &lt;/p&gt;

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

document.addEventListener('DOMContentLoaded', () =&amp;gt; {

})


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

&lt;/div&gt;

&lt;p&gt;You might be wondering what the &lt;code&gt;DOMContentLoaded&lt;/code&gt; event is and how it is different from the &lt;code&gt;load&lt;/code&gt; event. Even more, why did we choose to use it over the &lt;code&gt;load&lt;/code&gt; event? &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;DOMContentLoaded&lt;/code&gt; event is fired as soon as the &lt;code&gt;DOM&lt;/code&gt; tree has been created. This event does not wait for other resources such as the styles, images, data, and other external resources to be loaded. The &lt;code&gt;DOMContentLoaded&lt;/code&gt; is fired as soon as the elements of the page have been inserted into the DOM tree. On the other hand, the &lt;code&gt;load&lt;/code&gt; event waits a little longer before it is fired. The &lt;code&gt;load&lt;/code&gt; event is fired after all the resources of a page including styles, images, fetched data, and all other external resources have been loaded into the browser.&lt;/p&gt;

&lt;p&gt;Our interest in this project has nothing to do with external resources but everything to do with a few DOM elements. This is the reason why we are choosing to use the &lt;code&gt;DOMContentLoaded&lt;/code&gt; event over the &lt;code&gt;load&lt;/code&gt; event. The &lt;code&gt;load&lt;/code&gt; event could work just as well but we do not need to wait for that long. We want to attach the event listeners to the target element as soon as they are added to the &lt;code&gt;DOM&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We will perform all subsequent operations and listen for all the other required events within the &lt;code&gt;DOMContentLoaded&lt;/code&gt; event handler.&lt;/p&gt;

&lt;h3&gt;
  
  
  The drop zone container
&lt;/h3&gt;

&lt;p&gt;We want to make the drop zone container aware of the drag-drop interaction. Here, we will tell the browser what to do when a file is dropped within the borders of the drop-zone container. &lt;/p&gt;

&lt;p&gt;First, we need to get the drop zone container element from the &lt;code&gt;DOM&lt;/code&gt; as done below.&lt;/p&gt;

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

document.addEventListener('DOMContentLoaded', () =&amp;gt; {
    const dropZone = document.querySelector('#drop-zone')
})


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

&lt;/div&gt;

&lt;p&gt;Next, we attach the &lt;code&gt;drop&lt;/code&gt; event to the drop zone container and provide an event handler. &lt;/p&gt;

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

dropZone.addEventListener('drop', (event) =&amp;gt;{

    })


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

&lt;/div&gt;

&lt;p&gt;In the event handler, we will program the browser to treat the drag-and-drop interactions as a file input. This means that if the file is dragged and dropped within the borders of the drop zone container, the browser will override its default behavior with the program in the event handler function.  You can do anything with the dropped file. In our case, we will simply log the file information in the browser's console. Below is the implementation:&lt;/p&gt;

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

dropZone.addEventListener('dragover', (event) =&amp;gt;{
        event.preventDefault()

    })

 dropZone.addEventListener('drop', (event) =&amp;gt;{
        event.preventDefault()

        const files = event.dataTransfer.files

        console.log(files)
    })


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

&lt;/div&gt;

&lt;p&gt;The code snippet above adds two even listeners to the drop zone container, the &lt;code&gt;dragover&lt;/code&gt; and the &lt;code&gt;drop&lt;/code&gt; events. &lt;/p&gt;

&lt;p&gt;Technically, we only care about dropping the file within the borders of the container. So why bother with the &lt;code&gt;dragover&lt;/code&gt; event? We take care of the &lt;code&gt;dragover&lt;/code&gt; event because we are dragging the file over the drop zone container before we can drop it and the browser has a default behavior to the &lt;code&gt;dragover&lt;/code&gt; event. The least we can do about the default behavior of the browser is to prevent it. We access the files array from &lt;code&gt;event.dataTransfer&lt;/code&gt; and log the list on the browser console.&lt;/p&gt;

&lt;p&gt;Everything works well but the look, not very much so. In the next section, we will add styles to the process.  &lt;/p&gt;

&lt;h2&gt;
  
  
  4. Style the interaction
&lt;/h2&gt;

&lt;p&gt;What if you wanted to do more than prevent the default behavior of the browser? What if you intend to change the background color of the drag zone container throughout the process? Say one color when dragging over the drop zone container, a different color when you drag past the borders of the target container, and another color when you drop the file in the intended container. Well, that can easily be done as shown below. &lt;/p&gt;

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

 dropZone.addEventListener('dragover', (event) =&amp;gt;{
        event.preventDefault()

        dropZone.style.backgroundColor = '#e0e0e0'
    })

    dropZone.addEventListener('dragleave', () =&amp;gt;{
        dropZone.style.backgroundColor = '#eb6363a6'
    })

    dropZone.addEventListener('drop', (event) =&amp;gt;{
        event.preventDefault()

        dropZone.style.backgroundColor = '#f0f0f0'

        const files = event.dataTransfer.files

        console.log(files)
    })


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

&lt;/div&gt;

&lt;p&gt;The adjustments above involve altering the background color of the drop zone container from the initial background color to a gray color when the file is dragged into the drop zone container. The color changes to a shade of red if the drag leaves the container without dropping the file. Dropping the file resets the color to the initial background color. &lt;/p&gt;

&lt;p&gt;That's all good but didn't we say we could also click it? Up next ...&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Make it clickable
&lt;/h2&gt;

&lt;p&gt;The prompt in the container says we can also click the box to input a file. Unfortunately, clicking the box now doesn't open the file explorer as promised. How can we fix that? You guessed it right, add a click event listener to the container. &lt;/p&gt;

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

 dropZone.addEventListener('click', () =&amp;gt;{

    })


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

&lt;/div&gt;

&lt;p&gt;We have added the &lt;code&gt;click&lt;/code&gt; event listener, now what? &lt;/p&gt;

&lt;p&gt;In standard user interfaces, we trigger the opening of the file explorer by clicking a file input element that is displayed on a web page. In our case, we don't want to display a file input element. Lucky for us, we can add the element to the &lt;code&gt;DOM&lt;/code&gt; and hide it from display using the &lt;code&gt;hidden&lt;/code&gt; attribute. We can also click it programmatically using JavaScript. &lt;/p&gt;

&lt;p&gt;Extend the initial HTML markup to include the &lt;code&gt;input&lt;/code&gt; element as shown below:&lt;/p&gt;

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

&amp;lt;body&amp;gt;
    &amp;lt;!DOCTYPE html&amp;gt;
    &amp;lt;html lang="en"&amp;gt;
    &amp;lt;head&amp;gt;
      &amp;lt;meta charset="UTF-8"&amp;gt;
      &amp;lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&amp;gt;
      &amp;lt;title&amp;gt;Drag and Drop File Upload&amp;lt;/title&amp;gt;
      &amp;lt;link rel="stylesheet" href="./style.css"&amp;gt;
    &amp;lt;/head&amp;gt;
    &amp;lt;body&amp;gt;
      &amp;lt;div id="drop-zone" class="drop-zone"&amp;gt;
        &amp;lt;p&amp;gt;Drag &amp;amp; drop files here or click to upload&amp;lt;/p&amp;gt;
        &amp;lt;input type="file" id="file-input" multiple hidden&amp;gt;
      &amp;lt;/div&amp;gt;
      &amp;lt;script src="./drag-drop.js"&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;/body&amp;gt;
    &amp;lt;/html&amp;gt;

&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;


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

&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;hidden&lt;/code&gt; attribute allows us to exclude the input element from the display while keeping it in the &lt;code&gt;DOM&lt;/code&gt; tree.&lt;/p&gt;

&lt;p&gt;Now that we have the input element in the &lt;code&gt;DOM&lt;/code&gt;, we can access it from our JS scripts and click it programmatically when the drop zone container is clicked. The code snippet below implements the program.&lt;/p&gt;


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

&lt;p&gt;dropZone.addEventListener('click', () =&amp;gt;{&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    const fileInputElement = document.querySelector('input')
    fileInputElement.click()
})
&lt;/code&gt;&lt;/pre&gt;

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

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Summary&lt;br&gt;
&lt;/h2&gt;

&lt;p&gt;That is how we create a clickable drag-drop file input user interface. The drag-drop file input user interface uses the &lt;code&gt;DragEvent&lt;/code&gt; interface which provides the &lt;code&gt;dragover&lt;/code&gt;, &lt;code&gt;dragleave&lt;/code&gt;, &lt;code&gt;drop&lt;/code&gt;, and other browser events. When implementing the drag-drop file input, it is important to alter the styles of the drop target to improve the user experience. In addition to the drag-drop input, users will always appreciate an additional option for clicking the drop zone to open the file explorer. You can add a hidden file input element to your markup and click it programmatically when the drop zone is clicked. That's all for the article, thanks for reading. Feel free to say something in the comments section. Bye bye. &lt;/p&gt;

&lt;p&gt;Read more about &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/DragEvent" rel="noopener noreferrer"&gt;the &lt;code&gt;DragEvent&lt;/code&gt; interface on MDN&lt;/a&gt;.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Preview Your Images Instantly Before Uploading.</title>
      <dc:creator>Felix Owino</dc:creator>
      <pubDate>Sat, 06 Jul 2024 18:01:07 +0000</pubDate>
      <link>https://forem.com/ghostaram/preview-your-images-instantly-before-uploading-194</link>
      <guid>https://forem.com/ghostaram/preview-your-images-instantly-before-uploading-194</guid>
      <description>&lt;p&gt;We all have used modern websites where you get the pleasure of previewing the image you have selected for upload before you send it to the server. Image preview is such an interesting experience to have as user. You have seen this several times on social media. This is a common experience in most modern websites.&lt;/p&gt;

&lt;p&gt;As upcoming developers, we only get to see the default behavior when uploading files, that is an ugly display of the name of the image file alongside an ugly button that says 'Choose a file'. Now are you eager to find out what magic the developers of your favorite social media sites perform to make you happy about your pictures before sending them to the rest of the world? Yes, and this article will show you how to preview images on your websites before uploading. Perhaps you can also make the users of your websites as happy as you always are.&lt;/p&gt;

&lt;h2&gt;
  
  
  Writing the Markup code
&lt;/h2&gt;

&lt;p&gt;Previewing files is a such an easy task that we can accomplish with just about four lines of code. Before we go deeper into the magic of previewing the image, let us write some simple HTML code for selecting an image from your computer. &lt;/p&gt;

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

&amp;lt;style&amp;gt;
    *{
        font-family: sans-serif;
    }
    body{
        text-align: center;
        padding-block-start: 4rem;
    }
    button{
        background-color: #0369a1;
        color: #f1f5f9;
        border-radius: 4px;
        padding-inline: 1rem;
        padding-block: .5rem;
        border: none;
    }

    button:hover{
        opacity: .7;
        transition: all .75s;
    }

    input{
        display: none;
    }
&amp;lt;/style&amp;gt;
&amp;lt;body&amp;gt;
    &amp;lt;h1&amp;gt;Preview Before Upload&amp;lt;/h1&amp;gt;
    &amp;lt;input type="file" name="imageFile"&amp;gt;
    &amp;lt;button&amp;gt;Select Image&amp;lt;/button&amp;gt;
&amp;lt;/body&amp;gt;


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

&lt;/div&gt;

&lt;p&gt;The code snippet above renders a heading, a HTML input element for a file and a button named 'Select Image'. We have also included some CSS styles to improve the look and feel. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fvl73kvomxurq3majqknp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fvl73kvomxurq3majqknp.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the styles we have set the display property for the input element to none. Another unusual thing we have done is adding a button called 'Select Image'. Wondering why we have done this? For one reason, the default file selection component has an ugly display graphic so we can hide it from display and use something easier to style as a button. Another reason why we have used the button is to trigger file selection dialog even if we do not have the input element on display. This means that the input element is only hidden from display but its very much active.&lt;/p&gt;

&lt;h2&gt;
  
  
  Selecting the file
&lt;/h2&gt;

&lt;p&gt;The next thing we want to do is to give the button the ability to open the file selection dialog when clicked. Guessed how we are going to open the file input dialog using the button. Yes, you are right - by attaching a click event listener to the button. Well, that's true but what are we going to ask the browser in the event handler? Under default display conditions, we would click the file input element manually to open a file selection dialog. In this case we are going to ask the browser to click the file input element when the button is clicked. Once the event handler is executed the file input dialog for will be opened for us. Sounds brilliant, like an automation task, doesn't it? Enough with the words, let's implement what we have just said.&lt;/p&gt;

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

&amp;lt;script&amp;gt;
    const button  = document.querySelector('button')
    const fileInput = document.querySelector('input')

    button.addEventListener('click', () =&amp;gt;{
        fileInput.click()
    })
&amp;lt;/script&amp;gt;


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

&lt;/div&gt;

&lt;p&gt;That's it, we have instructed the browser to open the file input dialog when the 'Select Image' button is clicked. We click the button which has the click even handler. The click even handler clicks the input element. The input element opens the file selection dialog on for us. The screenshot below shows how the result would look like. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Ft8q19wxq8tkrorinqvb3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Ft8q19wxq8tkrorinqvb3.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Right now if we select a file from the input dialog, we don't see anything on the screen. That sucks, let see how to preview the image in the next section.&lt;/p&gt;

&lt;h2&gt;
  
  
  Displaying the Preview
&lt;/h2&gt;

&lt;p&gt;Previewing an image on the client side requires one Browser API called the &lt;code&gt;FileReader&lt;/code&gt;. The &lt;code&gt;FileReader&lt;/code&gt; is provided readily to us by JavaSript. The &lt;code&gt;FileReader&lt;/code&gt; allows us to asynchronously read content of a file in a way that can be displayed instantly. In the case of images, as data URL.&lt;/p&gt;

&lt;p&gt;The task we have here is to tell the browser to load the fil and render it instantly after loading. How are we going to do this ? Have you ever heard of a &lt;code&gt;change&lt;/code&gt; event? We can watch for the change event in the file input element, then do something when a file is selected. &lt;/p&gt;

&lt;p&gt;Let's start small, addi a &lt;code&gt;change&lt;/code&gt; event listener to the input element.&lt;/p&gt;

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

fileInput.addEventListener('change', (event) =&amp;gt;{
        //Do something here
   })


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

&lt;/div&gt;

&lt;p&gt;Next we will wait for the file to be loaded into the browser then get the image URL before trying to display it. &lt;/p&gt;

&lt;p&gt;The code snippet below implements the task described above.&lt;/p&gt;

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

fileInput.addEventListener('change', (event) =&amp;gt;{

        //Get the file from files array
        const file = event.target.files[0]

        if(file){
            const fileReader = new FileReader() 

     //Set up event listener to the fileReader before begining to read
            fileReader.onloadend = () =&amp;gt; {

                //Save the value read by the file reader in a variable
                const imageSrc = fileReader.result
            }

            // Tell the fileReader to read this file as URL
            fileReader.readAsDataURL(file) 
        }

    })


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

&lt;/div&gt;

&lt;p&gt;We now have a URL (&lt;code&gt;imageSrc&lt;/code&gt;) that we can use to render an image. To render an image we need an &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; element. We can create an image element using the &lt;code&gt;createElement&lt;/code&gt; method of the &lt;code&gt;document&lt;/code&gt; library. After creating the &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; element we can use it to display the image we have just loaded into the browser.&lt;/p&gt;

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

 fileInput.addEventListener('change', (event) =&amp;gt;{

        //Get the file from files array
        const file = event.target.files[0]

        if(file){
            const fileReader = new FileReader() 

            fileReader.onloadend = () =&amp;gt; {

                const imageSrc = fileReader.result

             // Create image element
                const img = document.createElement('img')

            // Assign value to the src attribute of the img element
                img.src = imageSrc

           // Add the image element to the body of the document
                document.body.appendChild(img)
            }

            fileReader.readAsDataURL(file) 
        }

    })


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

&lt;/div&gt;

&lt;p&gt;The code snippet added above enables us to preview before we can send it to the backend for storage. We created an image element,, assigned an image URL to it and rendered it. The image will be displayed instantly after selecting the file.&lt;/p&gt;

&lt;p&gt;An example of what we meant to achieve looks like the following screenshot:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fivrvexjbcsx912uonnjq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fivrvexjbcsx912uonnjq.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It looks like we have achieved what we wanted but we have a little problem. Have you tried selecting a second image? If you did then you must have realized that multiple images are displayed instead of the latest only. In this little experiment, we expect a new image to replace the existing image. &lt;/p&gt;

&lt;h2&gt;
  
  
  Preventing multiple image renders.
&lt;/h2&gt;

&lt;p&gt;The solution to rendering multiple images involves cleaning up the DOM every time we are rendering a new image. We clean up to ensure that there is no other image in the body of the document that we don't intend to display. &lt;/p&gt;

&lt;p&gt;The following code snippet finds and removes an &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; element if it exists in the body of the document.&lt;/p&gt;

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

... //the rest of the change event handler code
 fileReader.onloadend = () =&amp;gt; {

                //Save the value read by the file reader in a variable
                const imageSrc = fileReader.result



                //try to select the img tag
              const existingImgElement = document.querySelector('img')

 //Check if the tag is not null, it then remove it before rendering the next
                if(existingImgElement){
                    document.body.removeChild(existingImgElement)
                }



                const img = document.createElement('img')
                img.src = imageSrc
                document.body.appendChild(img)
            }

...//The rest of the change event handler code


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

&lt;/div&gt;

&lt;p&gt;In the above code snippet, we remove an &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tag from the body of the document just before creating a new one. We check if the value of the existing image element is truthy to avoid potential errors. Removing the existing &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tag from the body fixes the unintended rendering of multiple images.&lt;/p&gt;

&lt;p&gt;Finally, we have successfully learned how to preview an image instantly before uploading. Such a little improvement on your web apps can do a lot good to the user experience on your web apps. Previewing an image before upload can be done using the &lt;code&gt;FileReader&lt;/code&gt; API provided by JavaScript. A &lt;code&gt;loadend&lt;/code&gt; event handler can be added the &lt;code&gt;FileReader&lt;/code&gt; to to render the image after complete loading. The &lt;code&gt;FileReader&lt;/code&gt; reads the image as a data URL. The result of the file reader can be assigned directly to the &lt;code&gt;src&lt;/code&gt; attribute of the &lt;code&gt;img&lt;/code&gt; tag to display the image instantly after selecting it.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>frontend</category>
      <category>programming</category>
    </item>
    <item>
      <title>Understanding React States for Proper State Management.</title>
      <dc:creator>Felix Owino</dc:creator>
      <pubDate>Mon, 12 Feb 2024 08:45:32 +0000</pubDate>
      <link>https://forem.com/ghostaram/understanding-react-states-for-proper-state-management-1k7d</link>
      <guid>https://forem.com/ghostaram/understanding-react-states-for-proper-state-management-1k7d</guid>
      <description>&lt;p&gt;The most interesting thing any beginner gets to learn about React is the React state. Now the question is, what is the React state? Why do we call it a state? And most importantly, why do we need it in React applications? Not to forget about how we use it in React applications. In this article, we will learn about the React state, what it is, what it does, why we need it, and how to use it in React applications.&lt;/p&gt;

&lt;p&gt;We want to make our work in this learning exercise as easy as possible. For that reason, we will break down this topic into the following sections:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Foundational understanding of React States.&lt;/li&gt;
&lt;li&gt;The difference between States and Props.&lt;/li&gt;
&lt;li&gt;Immutability in React states and why is it important to keep states immutable.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By covering the above subtopics, you will have more than what you need to start using React states in your components. Let us begin by looking at the foundations of the React state.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Foundational Understanding of React State.
&lt;/h3&gt;

&lt;p&gt;Now if you are wondering about what React state is, this section will help you relax your mind about it. We will define what a state is with an example and discuss why React states are important.&lt;/p&gt;

&lt;p&gt;Before thinking about states in the technical sense, consider a state as an English word. What comes into your mind when you hear the word state? The current condition of something? What is currently happening around you? Well, all those make sense as states in the real world. &lt;/p&gt;

&lt;p&gt;In React, the state is a feature that enables React to keep track of the nature of data being rendered in each component. State enables a component to remember what it is supposed to render on every render. React provides an inbuilt hook called the &lt;code&gt;usesState&lt;/code&gt; hook that is used to handle states.&lt;/p&gt;

&lt;p&gt;Take for example a simple component that takes input of product quantity from the user and displays it on the screen:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0knf0ehnmkt4kkf1mhvr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0knf0ehnmkt4kkf1mhvr.png" alt="Initial product quantity" width="550" height="139"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The following code snippet describes the component that renders the elements shown in the screenshot above:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState } from 'react'

const ProductQuantity = () =&amp;gt; {
    const [quantity, setQuantity] = useState(0)

    return (
        &amp;lt;div&amp;gt;
            &amp;lt;input type="number" value={ quantity } onChange={
                (e) =&amp;gt; setQuantity(Number(e.target.value))
            } /&amp;gt;

            &amp;lt;h1&amp;gt; Current Quantity: { quantity }&amp;lt;/h1&amp;gt;
        &amp;lt;/div&amp;gt;
    )
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code snippet above does the following:&lt;/p&gt;

&lt;p&gt;i). It initializes the state called &lt;code&gt;quantity&lt;/code&gt; with the value  &lt;code&gt;0&lt;/code&gt; using the &lt;code&gt;useState&lt;/code&gt; hook &lt;/p&gt;

&lt;p&gt;ii). The useState hook returns an array containing the following two items:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A variable that keeps the initial value of the state &lt;/li&gt;
&lt;li&gt;A function that can be used to update the state. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this case, the state is stored in the variable named &lt;code&gt;quantity&lt;/code&gt; and the function for updating the quantity is called is stored in a variable called &lt;code&gt;setQuantity&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;ii). The component renders a number input field with a default value of &lt;code&gt;0&lt;/code&gt;. The text input field has a change event handler; an anonymous function that calls the updater function, &lt;code&gt;setQuantity&lt;/code&gt; with the value of the input.&lt;/p&gt;

&lt;p&gt;iv). Finally, the component renders the value of the &lt;code&gt;quantity&lt;/code&gt; in a heading tag.&lt;/p&gt;

&lt;p&gt;The value of the quantity can be changed to any number and it will be displayed instantly, for example, say you want to input a new quantity as &lt;code&gt;10000&lt;/code&gt;. It would look something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fns27w6o5c5cuqyqy75om.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fns27w6o5c5cuqyqy75om.png" alt="Update quantity" width="442" height="189"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Without the state variable and the state setter function, the component would not know that the value of &lt;code&gt;quantity&lt;/code&gt; has changed and therefore it should rerender the new value. States tell a component what to render.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. The difference between props and states.
&lt;/h3&gt;

&lt;p&gt;If you are sequentially learning React, you must have used props to supply data to components. Now you might be thinking that props also tell components what to render, why do we need to learn about this new concept called states? The thing is, props tell a component about the changes that occur outside the component and states tell a component what happens to the data inside itself. &lt;/p&gt;

&lt;p&gt;Let us adjust our  &lt;code&gt;ProductQuantity&lt;/code&gt; component to accept a prop. This time, let us supply a new value called &lt;code&gt;unitPrice&lt;/code&gt; to the component using a prop. We want to use this value to calculate the price of the products when we update the quantity. The final rendered component with a &lt;code&gt;unitPrice&lt;/code&gt; of &lt;code&gt;240&lt;/code&gt; would look like the screenshot below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm3yru5iidnog9mjuoozd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm3yru5iidnog9mjuoozd.png" alt="Quantity with unit price" width="689" height="200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can adjust our components to render the above information as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState } from 'react'

const ProductQuantity = ( { unitPrice }) =&amp;gt; {
    const [quantity, setQuantity] = useState(0)

    return (
        &amp;lt;div&amp;gt;
            &amp;lt;input type="text" value={ quantity } onChange={
                (e) =&amp;gt; setQuantity(Number(e.target.value))
            } /&amp;gt;

            &amp;lt;h1&amp;gt; Current Quantity: { quantity }&amp;lt;/h1&amp;gt;
            &amp;lt;h2&amp;gt;Unit Price: { unitPrice }&amp;lt;/h2&amp;gt;
            &amp;lt;h3&amp;gt; Total Cost: {quantity * unitPrice }&amp;lt;/h3&amp;gt;
        &amp;lt;/div&amp;gt;
    )
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code snippet above does the following new things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The component accepts a unit price prop (&lt;code&gt;unitPrice&lt;/code&gt;) of type number&lt;/li&gt;
&lt;li&gt;The component displays the unit price in a level 2 heading tag  (&lt;code&gt;h2&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Finally, the component calculates the total cost of the quantity of products entered and displays it in a level 3 heading tag &lt;code&gt;h3&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As we said earlier, &lt;code&gt;props&lt;/code&gt; are values supplied to a component by its parent component.  We can call our updated component in a parent component to supply the value of the &lt;code&gt;unitPrice&lt;/code&gt; prop, as shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    import ProductQuantity from './ProductQuantity'

    function App() {
        const unitPrice = 240

        return (
            &amp;lt;div&amp;gt;
                &amp;lt;ProductQuantity unitPrice={unitPrice} /&amp;gt;
            &amp;lt;/div&amp;gt;

        )
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From the above code snippets, we can see that props transfer information about changes that occur in the parent component (&lt;code&gt;App&lt;/code&gt;) while a state takes care of the changes that occur in the current component (&lt;code&gt;ProductQuantity&lt;/code&gt;). The prop (&lt;code&gt;unitPrice&lt;/code&gt;) is initialized and maintained in the parent component while the state (&lt;code&gt;quantity&lt;/code&gt;) is initialized and maintained by the current component.&lt;/p&gt;

&lt;p&gt;Now with the above setup, we can update the quantity of products and the total will be displayed instantly. For example, say we change the quantity of products to 29, the updated total will be displayed as shown below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk9syigtni1fnnganqd7g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk9syigtni1fnnganqd7g.png" alt="Updated total" width="672" height="226"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3.) Immutability in React states and why is it important to keep states immutable.
&lt;/h3&gt;

&lt;p&gt;What does it mean for something to be immutable? An immutable object is an object that cannot be changed. React states are technically mutable but it is recommended to treat them as if they are immutable. This means you should not modify a state during an update but you should replace it. &lt;/p&gt;

&lt;p&gt;For example, we can create a new component called &lt;code&gt;PurchasedProduct&lt;/code&gt; that takes, &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;quantity&lt;/code&gt;, and &lt;code&gt;unitPrice&lt;/code&gt; input from the user. The product renders the values of the product properties including gross total on the screen as shown below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flhiuyxpkvk90ddrsnh9i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flhiuyxpkvk90ddrsnh9i.png" alt="Inititial purchased product" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The code snippet below renders the elements shown in the screenshot above:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
import { useState } from 'react'

const PurchasedProduct = () =&amp;gt; {
    const [product, setProduct] = useState({
        name: '',
        quantity: 0,
        unitPrice: 0
    })
    return (
        &amp;lt;div&amp;gt;
            &amp;lt;div&amp;gt;
                Name: &amp;lt;input type="text" /&amp;gt;
                Quantity: &amp;lt;input type="number" /&amp;gt;
                Unit price: &amp;lt;input type="number" /&amp;gt;
            &amp;lt;/div&amp;gt;
            &amp;lt;h1&amp;gt;Name: {product.name}&amp;lt;/h1&amp;gt;
            &amp;lt;h1&amp;gt;Quantity: { product.quantity}&amp;lt;/h1&amp;gt;
            &amp;lt;h1&amp;gt;Unit price: {product.unitPrice }&amp;lt;/h1&amp;gt;
        &amp;lt;/div&amp;gt;
    )
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that we have not handled any change events in the input fields. To learn the importance of keeping states immutable, we will break down this section into the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a) Problems associated with mutating states&lt;/li&gt;
&lt;li&gt;b) How to maintain immutability while updating states&lt;/li&gt;
&lt;li&gt;c) Using the spread operator to update states&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  a) Problems associated with mutating states.
&lt;/h4&gt;

&lt;p&gt;One way to update the state of the product with the changes in input values would be to update every single property that is related to each input field. The code snippet is shown below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState } from 'react'

const PurchasedProduct = () =&amp;gt; {
    const [product, setProduct] = useState({
        name: '',
        quantity: 0,
        unitPrice: 0
    }) 

    const updateName = (e) =&amp;gt; { product.name = e.target.value }

    const updateQuantity = (e) =&amp;gt;{ product.quantity = Number(e.target.value) }

    const updateUnitPrice = (e) =&amp;gt;{ product.unitPrice = Number(e.target.value) }

    return (
        &amp;lt;div&amp;gt;
            &amp;lt;div&amp;gt;
                Name: &amp;lt;input type="text" onChange={updateName}/&amp;gt;
                Quantity: &amp;lt;input type="number" onChange={updateQuantity}/&amp;gt;
                Unit price: &amp;lt;input type="number" onChange={updateUnitPrice}/&amp;gt;
            &amp;lt;/div&amp;gt;
            &amp;lt;h1&amp;gt;Name: {product.name}&amp;lt;/h1&amp;gt;
            &amp;lt;h1&amp;gt;Quantity: { product.quantity}&amp;lt;/h1&amp;gt;
            &amp;lt;h1&amp;gt;Unit price: {product.unitPrice }&amp;lt;/h1&amp;gt;
        &amp;lt;/div&amp;gt;
    )
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Surprisingly, the code snippet above seems to be so simple and straight forward but it does not update any states. Nothing changes in the display at all when you try to change the values in the input field. The screenshot below shows all the input fields populated with input data but nothing new is rendered.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmn8o6nj1bcmkl0bl5mau.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmn8o6nj1bcmkl0bl5mau.png" alt="Mutated state" width="800" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is what happens when you try to change state directly like you would change the value of any variable. The state does not get updated at all and therefore no rerendering occurs.&lt;/p&gt;

&lt;p&gt;Let us try doing it differently, this time we will use, the &lt;code&gt;setProduct&lt;/code&gt; function to update the state.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const PurchasedProduct = () =&amp;gt; {
    const [product, setProduct] = useState({
        name: '',
        quantity: 0,
        unitPrice: 0
    }) 

    const updateName = (e) =&amp;gt; { setProduct({ name: e.target.value }) }

    const updateQuantity = (e) =&amp;gt;{ setProduct({ quantity:Number(e.target.value)} ) }

    const updateUnitPrice = (e) =&amp;gt;{ setProduct({ unitPrice: Number(e.target.value) }) }

    return (
        &amp;lt;div&amp;gt;
            &amp;lt;div&amp;gt;
                Name: &amp;lt;input type="text" onChange={updateName}/&amp;gt;
                Quantity: &amp;lt;input type="number" onChange={updateQuantity}/&amp;gt;
                Unit price: &amp;lt;input type="number" onChange={updateUnitPrice}/&amp;gt;
            &amp;lt;/div&amp;gt;
            &amp;lt;h1&amp;gt;Name: {product.name}&amp;lt;/h1&amp;gt;
            &amp;lt;h1&amp;gt;Quantity: { product.quantity}&amp;lt;/h1&amp;gt;
            &amp;lt;h1&amp;gt;Unit price: {product.unitPrice }&amp;lt;/h1&amp;gt;
        &amp;lt;/div&amp;gt;
    )
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's render our component with the above changes and see what happens. This time, we get something better. &lt;/p&gt;

&lt;p&gt;The first value, &lt;code&gt;name&lt;/code&gt;, updates as expected as shown below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fshjkzqvxqtxxnpu3byle.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fshjkzqvxqtxxnpu3byle.png" alt="Updated name field" width="765" height="390"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let us try the second value, product &lt;code&gt;quantity&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmixqsdgg1z4e3x0a01ct.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmixqsdgg1z4e3x0a01ct.png" alt="Updated quantity field" width="800" height="358"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we have a problem here, the second value updates well but the first one disappears.&lt;/p&gt;

&lt;p&gt;Let's see what happens with the last value, &lt;code&gt;unitPrice&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4za4h5mt15q4z94ryh94.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4za4h5mt15q4z94ryh94.png" alt="Updated Unit price" width="793" height="344"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Similarly, the unit price gets updated and rendered as expected but the rest of the values are not rerender as we expected. &lt;/p&gt;

&lt;p&gt;What is happening here? According to our code, we are updating a single property of the &lt;code&gt;product&lt;/code&gt;  object at every input field. This means that we are trying to modify the &lt;code&gt;product&lt;/code&gt; partially at every step. &lt;/p&gt;

&lt;p&gt;The problem with this approach is that every time we update just one value, the initial object is replaced with a new object with just one property. When we update the &lt;code&gt;name&lt;/code&gt;, we end up with a new object, &lt;code&gt;{name: &amp;lt;new name&amp;gt;}&lt;/code&gt;. The new object does not know anything about &lt;code&gt;unitPrice&lt;/code&gt; or &lt;code&gt;quantity&lt;/code&gt;. Updating the next value, &lt;code&gt;unitPrice&lt;/code&gt; does the same thing, it replaces the current object with a new object that has no &lt;code&gt;name&lt;/code&gt; or &lt;code&gt;quantity&lt;/code&gt; properties. Therefore, when the component is being rerendered, only one value gets rendered at a time, the most recent update.&lt;/p&gt;

&lt;h4&gt;
  
  
  b) How to maintain immutability when updating states.
&lt;/h4&gt;

&lt;p&gt;The correct way to update the state in the &lt;code&gt;PurchasedProduct&lt;/code&gt;  component is to replace the whole &lt;code&gt;product&lt;/code&gt; object with a new object containing all its properties. In other words, copy the object and only change the value you are interested in changing without losing the other values. The code snippet is shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const PurchasedProduct = () =&amp;gt; {
//The code that initializes the state goes here

    const updateName = (e) =&amp;gt; { 
        setProduct(
            { 
                name: e.target.value,
                quantity: product.quantity,
                unitPrice: product.unitPrice 
            }
        ) 
    }

    const updateQuantity = (e) =&amp;gt;{ 
        setProduct(
            { 
                name: product.name,
                quantity:Number(e.target.value),
                unitPrice: product.unitPrice
            } 
        ) 
    }

    const updateUnitPrice = (e) =&amp;gt;{ 
        setProduct(
            { 
                name: product.name,
                quantity: product.quantity,
                unitPrice: Number(e.target.value) 
            }
        ) 
    }

    return (
        //JSX goes here
    )
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the changes described in the above code snippet, we can now get a component that behaves just as we expect. In the screenshot below, all the input fields are filled and all the values are displayed as expected.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2t8yhlek7t9j1b5qgwgi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2t8yhlek7t9j1b5qgwgi.png" alt="All inputs rerenderd" width="800" height="358"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This shows that states are managed better when they are treated as immutable. Every time you are updating a state, make sure you are replacing the whole state variable and not just modifying its parts. This approach applies to array variables too. When working with arrays in states, consider replacing the whole array when adding or removing an item from the array.&lt;/p&gt;

&lt;h4&gt;
  
  
  c) Using the spread operator.
&lt;/h4&gt;

&lt;p&gt;A Less wordy approach to achieve the same goal above is to use the spread operator. The spread operator can save you a few lines of code and errors that you may introduce while copying the object. Below is a code snippet showing how the spread operator can make your life easier.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const PurchasedProduct = () =&amp;gt; {
//State initialization goes here

    const updateName = (e) =&amp;gt; { 
        setProduct(
            { 
                ...product,
                name: e.target.value
            }
        ) 
    }

    const updateQuantity = (e) =&amp;gt;{ 
        setProduct(
            { 
                ...product,
                quantity:Number(e.target.value),
            } 
        ) 
    }

    const updateUnitPrice = (e) =&amp;gt;{ 
        setProduct(
            { 
                ...product,
                unitPrice: Number(e.target.value) 
            }
        ) 
    }

    return (
       // JSX goes here
    )
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The spread operator enables you to override one property of the &lt;code&gt;product&lt;/code&gt; object and leave the rest as they are.&lt;/p&gt;

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

&lt;p&gt;In conclusion, understanding the React state as the memory of a component is crucial to the success of your user interface projects. In this article, we have learned the following concepts about React state:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How to initialize state using the useState hook&lt;/li&gt;
&lt;li&gt;How to update state using the &lt;code&gt;set&lt;/code&gt; state function&lt;/li&gt;
&lt;li&gt;The difference between states and props&lt;/li&gt;
&lt;li&gt;Problems associated with mutating states&lt;/li&gt;
&lt;li&gt;How to keep states immutable and why it is important to keep them immutable.&lt;/li&gt;
&lt;li&gt;How to update states using the spread operator.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Visit &lt;a href="https://react.dev/learn/render-and-commit"&gt;the react documentation&lt;/a&gt; to learn more about how state triggers rerendering in React applications.&lt;/p&gt;

</description>
      <category>react</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
    </item>
    <item>
      <title>How to set and customize horizontal and vertical scrollbars with CSS</title>
      <dc:creator>Felix Owino</dc:creator>
      <pubDate>Wed, 07 Feb 2024 07:56:05 +0000</pubDate>
      <link>https://forem.com/ghostaram/how-to-set-and-customize-horizontal-and-vertical-scrollbars-with-css-2f98</link>
      <guid>https://forem.com/ghostaram/how-to-set-and-customize-horizontal-and-vertical-scrollbars-with-css-2f98</guid>
      <description>&lt;p&gt;Scrollbars are essential components of graphical user interfaces (UI). Scrollbars allow users to view content that extends beyond the width or height of their containers. Scrollbars also enable users to view content that extends past the screen width or height. By default, the browser includes a scrollbar for overflow on the body content. In other cases, the UI developer has to set a scrollbar to enable users to view content extending beyond the screen or a particular container. Each browser has a set of default styles for scrollbars. In some cases, you may have a good reason to customize the scrollbars. For example, you can customize scrollbar styles to match the look and feel of the website. &lt;/p&gt;

&lt;p&gt;In this article, we will look at when to set horizontal and vertical scrollbars, how to set them, and how to customize their appearance with CSS.&lt;/p&gt;

&lt;p&gt;We will cover this topic in the following sections:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Setting up a custom vertical scrollbar&lt;/li&gt;
&lt;li&gt;Setting up a custom horizontal scrollbar&lt;/li&gt;
&lt;li&gt;Customizing scrollbar styles&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  1. Setting up a custom vertical scrollbar
&lt;/h2&gt;

&lt;p&gt;This is the most common type of scrollbar that users interact with on websites. The vertical scrollbar is so common because the browser sets a default vertical scrollbar for all websites. Apart from the default scrollbar, you can also set a custom vertical scrollbar within your website. A vertical scrollbar can help the users of your website view content that extends beyond the visible area of a container. For example, a sidebar navigation. You can style your sidebar to display a scrollable list of navigation items.&lt;/p&gt;

&lt;p&gt;In this section, we will create a scrollable sidebar navigation as per the following steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a) Create a navigation bar with navigation items&lt;/li&gt;
&lt;li&gt;b) Style the navigation bar into a sidebar&lt;/li&gt;
&lt;li&gt;c) Set the sidebar position to fixed&lt;/li&gt;
&lt;li&gt;d) Manage overflow of items using a scrollbar&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  a). Create a navigation bar with navigation items
&lt;/h3&gt;

&lt;p&gt;To create a navigation bar, we will use the HTML &lt;code&gt;nav&lt;/code&gt; element. Our navigation bar will contain the following items:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Home&lt;/li&gt;
&lt;li&gt;Shop&lt;/li&gt;
&lt;li&gt;Markets&lt;/li&gt;
&lt;li&gt;Products&lt;/li&gt;
&lt;li&gt;Sellers&lt;/li&gt;
&lt;li&gt;Manufacturers&lt;/li&gt;
&lt;li&gt;Distributors&lt;/li&gt;
&lt;li&gt;Chain managers&lt;/li&gt;
&lt;li&gt;Banks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Our aim in this step is to create a navigation bar shown in the screenshot below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Ff64mmneqvxrd2dab0n9t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Ff64mmneqvxrd2dab0n9t.png" alt="Navigation bar"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The initial navigation bar with the above items can be created using the code snippet shown below:&lt;/p&gt;

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

&amp;lt;style&amp;gt;
    a{
        padding: 1rem;
        color: rgb(38, 103, 216);
        text-decoration: none;
    }
&amp;lt;/style&amp;gt;
&amp;lt;body&amp;gt;
    &amp;lt;nav&amp;gt;
         &amp;lt;a&amp;gt;Home&amp;lt;/a&amp;gt;
        &amp;lt;a&amp;gt;Shop&amp;lt;/a&amp;gt;
        &amp;lt;a&amp;gt;Markets&amp;lt;/a&amp;gt;
        &amp;lt;a&amp;gt;Products&amp;lt;/a&amp;gt;
        &amp;lt;a&amp;gt;Sellers&amp;lt;/a&amp;gt;
        &amp;lt;a&amp;gt;Manufacturers&amp;lt;/a&amp;gt;
        &amp;lt;a&amp;gt;Distributors&amp;lt;/a&amp;gt;
        &amp;lt;a&amp;gt;Chain managers&amp;lt;/a&amp;gt;
        &amp;lt;a&amp;gt;Banks&amp;lt;/a&amp;gt;
    &amp;lt;/nav&amp;gt;
&amp;lt;/body&amp;gt;


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  b). Style the navigation bar into a sidebar.
&lt;/h3&gt;

&lt;p&gt;After creating our horizontal navigation bar, we can style it into a vertical sidebar before setting a vertical scrollbar. &lt;/p&gt;

&lt;p&gt;The following screenshot shows the sidebar that we are about to create:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F8k74d9edv6otorbfqwhi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F8k74d9edv6otorbfqwhi.png" alt="Sidebar"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To create the above sidebar, we will make the following changes in CSS:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Change the display of the navigation bar to flex with the direction set to column&lt;/li&gt;
&lt;li&gt;Set the background color for the sidebar&lt;/li&gt;
&lt;li&gt;Add a border to the bottom of the navigation links&lt;/li&gt;
&lt;li&gt;Increase font size and font weight of the navigation links&lt;/li&gt;
&lt;li&gt;Set a fixed width for the sidebar&lt;/li&gt;
&lt;li&gt;Increase the height of the body to make it long enough for scrolling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The CSS code snippet below describes how to style the initial navigation bar into a sidebar and adjust the margin-bottom of the body.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

    nav{
        display: flex;
        flex-direction: column;
        background-color: rgba(0, 0, 0, 0.1);
        width: 20vw; // Set fixed width for sidebar
        &amp;gt; a{
            border-bottom: solid 2px gray;
            font-weight: 500;
            font-size: 1.8rem;
        }
    }

    body{
        margin-bottom: 200vh; //Adjust the bottom margin of the body
    }


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  c). Set the sidebar position to fixed.
&lt;/h3&gt;

&lt;p&gt;In this section, we'll focus on preventing the sidebar from moving when you scroll through the main content. We want to style the sidebar so that the body can scroll on its own without carrying the sidebar along with it. &lt;/p&gt;

&lt;p&gt;The screenshot below shows the sidebar separated from the normal content flow:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F5stujkp3x6j2epnf4np2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F5stujkp3x6j2epnf4np2.png" alt="fixed overflown sidebar"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The sidebar above has a fixed position. The body of the page continues to scroll but the sidebar remains within the user's view. &lt;/p&gt;

&lt;p&gt;The following code snippet contains styles for setting the sidebar into a fixed position as shown in the above screenshot:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

nav{
        /* previous styles go here */
        position: fixed;
        top: 4rem;
        bottom: 4rem;
        left: 0;
    }


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

&lt;/div&gt;

&lt;p&gt;In the code snippet above, we have set the sidebar distance from the top and bottom to &lt;code&gt;4rem&lt;/code&gt;. From the screenshot, the bottom of the sidebar doesn't look like it is set off the bottom. This is because the content is longer than the height of its container. In the next section, we will learn how to prevent the list of navigation items from displaying outside the sidebar.&lt;/p&gt;

&lt;h3&gt;
  
  
  d). Managing content overflow using a scrollbar
&lt;/h3&gt;

&lt;p&gt;Preventing navigation items from displaying outside the sidebar is surprisingly easy. This can be done in one line of CSS code using the &lt;code&gt;overflow-y&lt;/code&gt; property. Setting the &lt;code&gt;overflow-y&lt;/code&gt; property to &lt;code&gt;scroll&lt;/code&gt; creates a scrollable container for content exceeding its height. The items that extend beyond the sidebar will be obscured. A scrollbar will appear on the right side, allowing the users of your website to see everything.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fhu0la8brgo9arg18zn8f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fhu0la8brgo9arg18zn8f.png" alt="Scrollable sidebar"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The code snippet for hiding the extended content and showing the sidebar is as simple as shown below:&lt;/p&gt;

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

    nav{
        /* previous styles go here */
        overflow-y: scroll;
    }


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  More about the &lt;code&gt;overflow-y&lt;/code&gt; property.
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;overflow-y&lt;/code&gt; property accepts either of the two values; &lt;code&gt;scroll&lt;/code&gt; or &lt;code&gt;auto&lt;/code&gt;. Setting the value of the property to &lt;code&gt;scroll&lt;/code&gt; instructs the browser to always add a scrollbar to the container. The container will always have a scrollbar whether it has content extending past its boundaries or not. On the other hand, if you set the value of the overflow-y property to &lt;code&gt;auto&lt;/code&gt;, the browser will not add the scrollbar unless the target container has extended content. With the value of the  &lt;code&gt;overflow-y&lt;/code&gt; property set to &lt;code&gt;auto&lt;/code&gt;, the browser will hide the scrollbar if there is no content extending beyond the boundaries of the container.&lt;/p&gt;

&lt;p&gt;Congratulations! You have successfully created a vertical scrollbar. Take a break if you need one. In the next section, we will learn how to set a horizontal scrollbar.&lt;/p&gt;
&lt;h2&gt;
  
  
  2. Setting a custom horizontal Scrollbar.
&lt;/h2&gt;

&lt;p&gt;You can add a horizontal scrollbar to a container within your webpage. The horizontal scrollbar can enable users to view a long series of horizontal content within a shorter container.&lt;/p&gt;

&lt;p&gt;The screenshot below shows an orange container with a series of blue squares that extend beyond its width. The container would look much better if the container had a horizontal scrollbar.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fr5d97deaigcgc947x1yd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fr5d97deaigcgc947x1yd.png" alt="Overflowing flexbox"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Below is the code snippet for the above layout:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&amp;lt;style&amp;gt;
    .container{
        display: flex;
        flex-direction: row;
        width: 60%;
        margin: auto;
        margin-block-end: 6rem;
        gap: .5rem;
        padding: 1rem;
        background-color: rgb(226, 150, 9);
    }
    .box{
        min-width: 200px;
        height: 200px;
        background-color: rgb(0, 255, 213);
        width: 100%;
        padding: 4rem;
        font-size: xx-large;
    }
&amp;lt;/style&amp;gt;
&amp;lt;body&amp;gt;
    &amp;lt;div class="container"&amp;gt;
        &amp;lt;div class="box"&amp;gt;1&amp;lt;/div&amp;gt;
        &amp;lt;div class="box"&amp;gt;2&amp;lt;/div&amp;gt;
        &amp;lt;div class="box"&amp;gt;3&amp;lt;/div&amp;gt;
        &amp;lt;div class="box"&amp;gt;4&amp;lt;/div&amp;gt;
        &amp;lt;div class="box"&amp;gt;5&amp;lt;/div&amp;gt;
        &amp;lt;div class="box"&amp;gt;6&amp;lt;/div&amp;gt;
        &amp;lt;div class="box"&amp;gt;7&amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/body&amp;gt;


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

&lt;/div&gt;

&lt;p&gt;The page has a default horizontal scrollbar at the bottom left corner of the screen but you don't want the users of your website to use this. Relying on the default scrollbar would mean that the users will have to scroll the whole page horizontally to see full content. The users will also be scrolling through content that does not need to be scrolled.&lt;/p&gt;

&lt;p&gt;Your goal is to make sure that the blue squares can only be viewed within the orange container as shown in the layout below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F5lipqmu9mirfhsjd4xam.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F5lipqmu9mirfhsjd4xam.png" alt="Scrollable container"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the previous section, we added a scrollbar by setting the value of the &lt;code&gt;overflow-y&lt;/code&gt;  property to scroll. You can guess what this is going to be. You got it. The property is called &lt;code&gt;overflow-x&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Set the value of the &lt;code&gt;overflow-x&lt;/code&gt; property to &lt;code&gt;scroll&lt;/code&gt; to make the container items scrollable as shown in the code snippet below. &lt;/p&gt;

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

 .container{
        /*previous container styles go here */

        overflow-x: scroll; //Managing oveflow with scroll.
    }


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

&lt;/div&gt;

&lt;p&gt;By setting the the value of &lt;code&gt;overflow-x&lt;/code&gt; property to &lt;code&gt;scroll&lt;/code&gt;,  a horizontal scrollbar is added to the bottom of the container. The users of your website will be able to smoothly scroll through the content in the container. &lt;/p&gt;

&lt;p&gt;You have successfully created both horizontal and vertical scrollbars. Let us move to the next section where we are going to discuss how to style the scrollbars.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Customizing scrollbar styles
&lt;/h2&gt;

&lt;p&gt;One of the reasons why you would want to style the scrollbars of your website is to attain color harmony on the entire webpage. You may want to keep the number of colors used on your website to a set minimum. You may also want to use a different color for the scrollbar to make it easy to notice.&lt;/p&gt;

&lt;p&gt;When styling the scrollbar, we can set desired values to the following properties:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;width&lt;/code&gt; - the thickness of a vertical scrollbar&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;height&lt;/code&gt; - the thickness of a horizontal scrollbar&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;background-color&lt;/code&gt; of the scrollbar-thumb  - the object that moves back and forth on a scrollbar as you scroll&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;background-color&lt;/code&gt; of the &lt;code&gt;scrollbar-track&lt;/code&gt; - the path along which the &lt;code&gt;scrollbar-thumb&lt;/code&gt; moves&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;border-radius&lt;/code&gt; for &lt;code&gt;scrollbar-track&lt;/code&gt;,  or &lt;code&gt;scrollbar-thumb&lt;/code&gt;, or both. The &lt;code&gt;border-radius&lt;/code&gt; property smoothens the extreme ends of the scrollbar component that it is set on.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this section, we will explore the different ways of styling scrollbars as listed below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a) Styling a specific scrollbar.&lt;/li&gt;
&lt;li&gt;b) Styling the default scrollbar separately. &lt;/li&gt;
&lt;li&gt;c) Styling all scrollbars at once&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  a). Styling a specific scrollbar.
&lt;/h3&gt;

&lt;p&gt;There is an easy way to set specific styles to different an individual scrollbar on a website. This involves adding styles through the container that the scrollbar is set on. You can select the container by tag name or by class name and assign styles to it.&lt;/p&gt;

&lt;p&gt;In this section, we will style the vertical scrollbar (sidebar) and the horizontal scrollbar (flexbox) separately. &lt;/p&gt;

&lt;h4&gt;
  
  
  Styling vertical scrollbar (sidebar scroll)
&lt;/h4&gt;

&lt;p&gt;We will set the following styles on the sidebar (vertical) scrollbar.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set the &lt;code&gt;background-color&lt;/code&gt; of the &lt;code&gt;scrollbar-track&lt;/code&gt; to blue&lt;/li&gt;
&lt;li&gt;Set the &lt;code&gt;background-color&lt;/code&gt; of the &lt;code&gt;scrollbar-thumb&lt;/code&gt; to green&lt;/li&gt;
&lt;li&gt;Set the &lt;code&gt;width&lt;/code&gt; (thickness) of the scrollbar to 12px&lt;/li&gt;
&lt;li&gt;Set the &lt;code&gt;border-radius&lt;/code&gt; of the &lt;code&gt;scrollbar-track&lt;/code&gt; and &lt;code&gt;scrollbar-thumb&lt;/code&gt; to 12px.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result we aim to create is shown in the screenshot below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F5pfyk1uey2tyafk7cp6n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F5pfyk1uey2tyafk7cp6n.png" alt="Styled vertical scrollbar"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The following code snippet describes the styles used to achieve the above result:&lt;/p&gt;

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

    nav::-webkit-scrollbar{
        width: 12px;
    }

    nav::-webkit-scrollbar-track{
        background-color: rgb(21, 146, 171);
        border-radius: 12px;
    }

    nav::-webkit-scrollbar-thumb{
        background-color: rgb(31, 125, 2);
        border-radius: 12px;
    }


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

&lt;/div&gt;

&lt;p&gt;In the above code snippet, we select the sidebar using the &lt;code&gt;nav&lt;/code&gt; tag.&lt;/p&gt;

&lt;h4&gt;
  
  
  Styling the horizontal scrollbar (flexbox scrollbar)
&lt;/h4&gt;

&lt;p&gt;Styling the horizontal scrollbar is similar to styling a vertical scrollbar except for one property. The &lt;code&gt;height&lt;/code&gt; property is used to set the thickness of a horizontal scrollbar instead of the &lt;code&gt;width&lt;/code&gt; property. &lt;/p&gt;

&lt;p&gt;In this exercise, we'll reuse previous styles, but we will set the thickness of the scrollbar using the &lt;code&gt;height&lt;/code&gt; as described below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set the &lt;code&gt;background-color&lt;/code&gt; of the &lt;code&gt;scrollbar-track&lt;/code&gt; to blue&lt;/li&gt;
&lt;li&gt;Set the &lt;code&gt;background-color&lt;/code&gt; of the &lt;code&gt;scrollbar-thumb&lt;/code&gt; to green&lt;/li&gt;
&lt;li&gt;Set the &lt;code&gt;height&lt;/code&gt; (thickness) of the scrollbar to 12px&lt;/li&gt;
&lt;li&gt;Set the &lt;code&gt;border-radius&lt;/code&gt; of the &lt;code&gt;scrollbar-track&lt;/code&gt; and &lt;code&gt;scrollbar-thumb&lt;/code&gt; to 12px.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After applying the styles as described above, the final flexbox container scrollbar should appear as shown below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F52fjdfei2zoismero61x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F52fjdfei2zoismero61x.png" alt="Styled horizontal scrollbar"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Below is the code snippet for customizing the horizontal scrollbar:&lt;/p&gt;

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

    .container::-webkit-scrollbar{
        height: 12px;
    }

    .container::-webkit-scrollbar-track{
        background-color: rgb(21, 146, 171);
        border-radius: 12px;
    }

    .container::-webkit-scrollbar-thumb{
        background-color: rgb(31, 125, 2);
        border-radius: 12px;
    }


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

&lt;/div&gt;

&lt;p&gt;In the above styles, we select the flexbox using its class name and apply styles to it.&lt;/p&gt;

&lt;h3&gt;
  
  
  b). Styling the default scrollbar
&lt;/h3&gt;

&lt;p&gt;The default scrollbar appears on the right-hand side of a webpage. To style the default scrollbar, we select the body tag and add styles to it. &lt;/p&gt;

&lt;p&gt;The screenshot below shows a default scrollbar with custom styles:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Ftz5rrjgpdit0jo48fw6a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Ftz5rrjgpdit0jo48fw6a.png" alt="Styled default scrollbar"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The code snippet below shows how you can add styles to the scrollbar using the body tag:&lt;/p&gt;

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

    body::-webkit-scrollbar{
        width: 12px;
    }

    body::-webkit-scrollbar-track{
        background-color: rgb(21, 146, 171);
        border-radius: 12px;
    }

    body::-webkit-scrollbar-thumb{
        background-color: rgb(31, 125, 2);
        border-radius: 12px;
    }


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  c). Styling all scrollbars at once.
&lt;/h3&gt;

&lt;p&gt;In most cases, you will prefer to maintain a consistent style across all the vertical and horizontal scrollbars on your website. &lt;/p&gt;

&lt;p&gt;To achieve uniform customization across all scrollbars, we can apply styles as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Apply scrollbar styles without selecting any specific element, tag, or class name&lt;/li&gt;
&lt;li&gt;Assign values to both &lt;code&gt;height&lt;/code&gt; and &lt;code&gt;width&lt;/code&gt; properties in the case where a website has both horizontal and vertical scrollbars.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The screenshot below shows horizontal and vertical scrollbars with consistent styles:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fu59chjo94vaz8gx9wetg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fu59chjo94vaz8gx9wetg.png" alt="All scrollbars styled"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When applying CSS styles, make sure you set values for both the &lt;code&gt;height&lt;/code&gt; and &lt;code&gt;width&lt;/code&gt; properties. The value of the &lt;code&gt;height&lt;/code&gt; will be applied to the thickness of the horizontal scrollbar. The value of the &lt;code&gt;width&lt;/code&gt; will be applied to the thickness of the vertical scroll bar.&lt;/p&gt;

&lt;p&gt;The following code snippet shows how you can apply styles to all scrollbars on the target webpage:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

    ::-webkit-scrollbar{
        height: 12px;
        width: 12px;
    }

    ::-webkit-scrollbar-track{
        background-color: rgb(21, 146, 171);
        border-radius: 12px;
    }

    ::-webkit-scrollbar-thumb{
        background-color: rgb(31, 125, 2);
        border-radius: 12px;
    }


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

&lt;/div&gt;

&lt;p&gt;Notice in the above code that this time we are not selecting any element or class in specific. The styles are global; and applicable to all scrollbars on the document. &lt;/p&gt;

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

&lt;p&gt;Scrollbars are a great way to improve the responsiveness and accessibility of your web application. This article has covered how to set and customize the appearance of scrollbars on a web page. In this article we have learned the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How to enable scrolling in containers with content that extends beyond their set boundaries.&lt;/li&gt;
&lt;li&gt;How to make a scrollbar permanently visible in a container even if the content fits perfectly.&lt;/li&gt;
&lt;li&gt;How to set a scrollbar that will only be visible if the content extends beyond the container.&lt;/li&gt;
&lt;li&gt;How to add custom styles to scrollbars.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We have also learned how to style scrollbars using the &lt;code&gt;-webkit CSS prefix&lt;/code&gt;. Find out more about the &lt;code&gt;-webkit&lt;/code&gt; CSS prefix in &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/WebKit_Extensions" rel="noopener noreferrer"&gt;this article&lt;/a&gt;. There are other ways to style scrollbars. For example, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_scrollbars_styling" rel="noopener noreferrer"&gt;this article from MDN&lt;/a&gt; describes a different way to style scrollbars. Note that scrollbar customizations may not work on all browsers. &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/::-webkit-scrollbar#browser_compatibility" rel="noopener noreferrer"&gt;Visit this MDN doc&lt;/a&gt; to find out more about browser compatibility with the styling method described in this article.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>css</category>
    </item>
    <item>
      <title>How to Populate Database with Test Data.</title>
      <dc:creator>Felix Owino</dc:creator>
      <pubDate>Mon, 20 Nov 2023 22:02:28 +0000</pubDate>
      <link>https://forem.com/ghostaram/how-to-populate-test-database-with-data-133d</link>
      <guid>https://forem.com/ghostaram/how-to-populate-test-database-with-data-133d</guid>
      <description>&lt;p&gt;Testing is vital in the software development life cycle. During the software development, you occasionally need to test your application against data. One way to acquire test data is through manual entry. The problem with manual entry is that it's limited.  There is only so much data you can enter manually. A better option is to load the data to your database using a program separate from your application. In this article, we will learn how to write a program to upload test data to a test database.&lt;/p&gt;

&lt;p&gt;To learn smoothly from this article, you should have a basic knowledge of the following.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creating simple programs with Node JS&lt;/li&gt;
&lt;li&gt;Working with Mongo DB&lt;/li&gt;
&lt;li&gt;Working with a database abstraction library. We will use Mongoose in this article.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We will learn how to upload test data to the database by performing the following actions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a data model.&lt;/li&gt;
&lt;li&gt;Fetch raw data from an API.&lt;/li&gt;
&lt;li&gt;Connect to the database.&lt;/li&gt;
&lt;li&gt;Populate the database with documents.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  1. Create data model
&lt;/h2&gt;

&lt;p&gt;Data models are essential in loading test data to the database. Models define the shape and properties of the data to be uploaded. The shape of the data you upload should be compatible with the specifications of our application. You need to create the same models as they are in the application you intenf to test. In this article, we will assume a todos model.&lt;/p&gt;

&lt;p&gt;To define a model we need to install Mongoose using the command below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install mongoose
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we define the &lt;code&gt;Todo&lt;/code&gt; model as follows.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Model, Schema, model } from "mongoose"

interface ITodo{
    title: string
    completed?: boolean
}

type TodoModel = Model&amp;lt;ITodo&amp;gt;

const todoSchema = new Schema&amp;lt;ITodo, TodoModel&amp;gt;({
    title: String,
    completed: { type: Boolean, default: false}
})

export const Todo = model&amp;lt;ITodo, TodoModel&amp;gt;('Todo', todoSchema)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will use the above model to upload data to the database. &lt;/p&gt;

&lt;p&gt;Next, we fetch the raw data that we will use to create documents from the model.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Fetch data
&lt;/h2&gt;

&lt;p&gt;In the previous step, we created a model for our data. In this section, we will get the raw data that we will use to create documents. We will fetch the raw data &lt;a href="https://jsonplaceholder.typicode.com"&gt;this fake data API&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Below is the code snippet that fetches the raw data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(async() =&amp;gt;{
    try {
        const response = await fetch('https://jsonplaceholder.typicode.com/todos')
        const rawData = await response.json()


    } catch (error: any) {
        console.log(error.message)
    }

})()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After fetching the data from the API, let us connect the database in the next step before we can create documents.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Connect to the database.
&lt;/h2&gt;

&lt;p&gt;Before sending data to the database, we need to connect to MongoDB. Get the connection string for your test database and connect to the database as shown in the code snippet below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import mongoose from "mongoose"

(async() =&amp;gt;{
    try {
        const response = await fetch('https://jsonplaceholder.typicode.com/todos')
        const rawData = await response.json()

        const dbUri = 'Your db uri'

        if(dbUri){
            await mongoose.connect(dbUri)
        }

    } catch (error: any) {
        console.log(error.message)
    }

})()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we have a database ready to receive our data, let us create documents and save them to the database in the next section.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Populate the database with documents.
&lt;/h2&gt;

&lt;p&gt;In this section, we will create and save &lt;code&gt;Todo&lt;/code&gt; documents for each instance of data in the &lt;code&gt;rawData&lt;/code&gt; array. The code snippet below creates and saves data using the &lt;code&gt;Todo.create&lt;/code&gt; method. We also log the &lt;code&gt;id&lt;/code&gt; of the document we create.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import mongoose from "mongoose"
import { Todo } from "./model"

(async() =&amp;gt;{
    try {
        const response = await fetch('https://jsonplaceholder.typicode.com/todos')
        const rawData = await response.json()

        const dbUri = process.env.MONGODB_URI

        if(dbUri){
            await mongoose.connect(dbUri)

            //Populated db with documents   
            rawData.forEach(async(todo:any) =&amp;gt; {
                const todoDoc = await Todo.create({
                    title: todo?.title,
                    completed: false
                })

                console.log('Created: ', todoDoc.id)
            })
        }

    } catch (error: any) {
        console.log(error.message)
    }

})()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The execution of the above program populates the target database with &lt;code&gt;Todo&lt;/code&gt; documents.&lt;/p&gt;

&lt;p&gt;Finally, we have created a program that loads data that matches our model specification to the database. The program loads the data to the database by following steps listed below: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a model that fits the shape of the expected test data.&lt;/li&gt;
&lt;li&gt;Fetch raw data from the &lt;a href="https://jsonplaceholder.typicode.com/"&gt;jsonplaceholder API&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Iterate over the test data and create a document for each instance of the raw data using the &lt;code&gt;Todo&lt;/code&gt; model.&lt;/li&gt;
&lt;li&gt;Save the documents to the database.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The code we have written in this article and other well refactored examples on the same topic is available on &lt;a href="https://github.com/GHOST-Aram/db-populator"&gt;this repository&lt;/a&gt;.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Testing Express API Routes the Easy Way: Beginners' guide.</title>
      <dc:creator>Felix Owino</dc:creator>
      <pubDate>Sun, 19 Nov 2023 04:50:31 +0000</pubDate>
      <link>https://forem.com/ghostaram/testing-express-api-routes-the-easy-way-beginners-guide-1mmi</link>
      <guid>https://forem.com/ghostaram/testing-express-api-routes-the-easy-way-beginners-guide-1mmi</guid>
      <description>&lt;p&gt;Unit testing is one of the best practices in software development. In the development of web APIs, there is no question about the importance of unit testing. Unit testing is critical in ensuring that all the routes in a web API respond with the information expected from them. &lt;/p&gt;

&lt;p&gt;Testing routes in a web API can be a nightmare if you don't structure your components well. One area that causes the most pain for beginners in testing APIs is the routes that involve database access. Database operations are inevitable. Often you are going to build CRUD applications as a beginner. In this article, we will learn how to test API routes with the least difficulty possible. &lt;/p&gt;

&lt;h2&gt;
  
  
  What will this article cover?
&lt;/h2&gt;

&lt;p&gt;The main focus of this article is to show you how to test routes. Therefore, other related tests such as database tests are out of the scope of this article.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does the article expect you to already know?
&lt;/h2&gt;

&lt;p&gt;This article is not an introductory tutorial to unit testing or API development. Therefore, we assume that you have basic knowledge of the following topics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unit testing with JavaScript libraries like &lt;a href="https://jestjs.io/" rel="noopener noreferrer"&gt;Jest&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://jestjs.io/docs/mock-functions" rel="noopener noreferrer"&gt;Mocking&lt;/a&gt; expensive operations in unit tests with the Jest mock functions. &lt;/li&gt;
&lt;li&gt;Creating simple CRUD APIs using Express.&lt;/li&gt;
&lt;li&gt;Working with Mongoose for database operations.&lt;/li&gt;
&lt;li&gt;Working with Typescript(optional but a plus if you know).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are new to Typescript, do not fret. Everything that we will cover in this article can be done even more easily with plain Javascript. &lt;/p&gt;

&lt;h2&gt;
  
  
  What technologies are we going to use?
&lt;/h2&gt;

&lt;p&gt;We will use the following technologies, frameworks, and libraries in this article:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Jest&lt;/li&gt;
&lt;li&gt;Supertest&lt;/li&gt;
&lt;li&gt;Node v20&lt;/li&gt;
&lt;li&gt;Typescript&lt;/li&gt;
&lt;li&gt;Express&lt;/li&gt;
&lt;li&gt;Mongoose&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What should you expect to learn from this article?
&lt;/h2&gt;

&lt;p&gt;At the end of this article, you will have learned how to do the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Separate your tests from the main application.&lt;/li&gt;
&lt;li&gt;Modularize your application for easy testing.&lt;/li&gt;
&lt;li&gt;Test routes that involve database operations without connecting to a database. &lt;/li&gt;
&lt;li&gt;Run tests successfully regardless of whether your application runs on a server.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How are we going to learn?
&lt;/h2&gt;

&lt;p&gt;Here is the order in which we are going to learn how to test API routes the easy way:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Configure a test environment.&lt;/li&gt;
&lt;li&gt;Create a simple Express API.&lt;/li&gt;
&lt;li&gt;Modularize your application for easy testing.&lt;/li&gt;
&lt;li&gt;Write your first route test.&lt;/li&gt;
&lt;li&gt;Write a test involving database operation.&lt;/li&gt;
&lt;li&gt;Decouple the data-access logic from the web layer.&lt;/li&gt;
&lt;li&gt;Introduce dependencies on the controller and the router.&lt;/li&gt;
&lt;li&gt;Mock your data-access layer.&lt;/li&gt;
&lt;li&gt;Replace the data access layer with the mock in the test file.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  1. Configure a test environment.
&lt;/h2&gt;

&lt;p&gt;In the spirit of "Do not repeat yourself," we will use a preexisting test environment. We will &lt;a href="https://github.com/GHOST-Aram/ts-jest-env" rel="noopener noreferrer"&gt;clone a configured test environment&lt;/a&gt; from a GitHub repository. This repository contains configurations for Jest and Typescript. In case you are interested in learning how to configure a test environment for Jest and Typescript, &lt;a href="https://dev.to/ghostaram/configuring-jest-for-typescript-unit-tests-4iag"&gt;visit this article&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After cloning the repository, run the following command to install node modules.&lt;/p&gt;

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

npm install


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

&lt;/div&gt;

&lt;p&gt;That's it. We have a development and test environment ready for us to work on. Let's move to step 2 and create a simple Express API.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Create a simple Express API.
&lt;/h2&gt;

&lt;p&gt;Because you already know how to create an API with Node and Express, we will go through this step quickly so we can start working on why you are here.&lt;/p&gt;

&lt;p&gt;Run the following command on your terminal to install Express and it's types.&lt;/p&gt;

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

npm i express
npm i -D @types/express


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

&lt;/div&gt;

&lt;p&gt;In your &lt;code&gt;src&lt;/code&gt; directory, create an &lt;code&gt;app.ts&lt;/code&gt; file and paste the following code snippet.&lt;/p&gt;

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

app.ts


import express from "express"

const api = express()

api.use(express.urlencoded({ extended: true }))
api.use(express.json())

api.get('/', (req, res) =&amp;gt;{
    res.status(200).json({message: 'Welcome to my API'})
})


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

&lt;/div&gt;

&lt;p&gt;There we go. That's all we need for now. Notice that we are not connecting to a database or listening on a port. We do not need database connectivity or a running instance of our application to be able to test it.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Modularize your application for easy testing.
&lt;/h2&gt;

&lt;p&gt;To enable efficient testing of the routes of our application, we need to modularize it into its individual components. &lt;/p&gt;

&lt;p&gt;We will decouple our API into routes, controllers, and the main file(&lt;code&gt;app.ts&lt;/code&gt;). We follow the steps below:&lt;/p&gt;

&lt;p&gt;a). Modularize route handlers.&lt;/p&gt;

&lt;p&gt;b). Modularize routes.&lt;/p&gt;

&lt;p&gt;c). Refactor the main file&lt;/p&gt;

&lt;h3&gt;
  
  
  a). Modularize router handlers
&lt;/h3&gt;

&lt;p&gt;Create a &lt;code&gt;controller.ts&lt;/code&gt; file in the &lt;code&gt;src&lt;/code&gt; directory. Create and export a route handler on the file as shown below.&lt;/p&gt;

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

controller.ts


import { Request, Response } from "express";

export const index = (req: Request, res: Response) =&amp;gt;{
    res.status(200).json({ message: 'Welcome to my API' })
}


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  b). Modularize routes
&lt;/h3&gt;

&lt;p&gt;i). Create a &lt;code&gt;routes.ts&lt;/code&gt; file in the &lt;code&gt;src&lt;/code&gt; directory. &lt;/p&gt;

&lt;p&gt;ii). Create a &lt;code&gt;router&lt;/code&gt; from &lt;code&gt;express.Router&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;iii). Import the controller function, and set up a route as shown below.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

routes.ts


import { Router } from "express";
import { index } from "./controller";

const router = Router()

router.get('/', index)

export {router}


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  c). Refactor the main file
&lt;/h3&gt;

&lt;p&gt;Import the router into &lt;code&gt;app.ts&lt;/code&gt; and replace the route handler as below.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

app.ts


import express from "express"
import { router } from "./routes"

const api = express()

api.use(express.urlencoded({ extended: true }))
api.use(express.json())

api.use('/', router)


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

&lt;/div&gt;

&lt;p&gt;We have successfully modularized our application for easy testing. Get ready to write your first route test in the next step.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Write your first route test.
&lt;/h2&gt;

&lt;p&gt;In the previous sections, we have created a simple Express API and modularised it for easy testing. Let us write a test for the index route (&lt;code&gt;/home&lt;/code&gt;). &lt;/p&gt;

&lt;p&gt;To write our first test, we will follow the steps below:&lt;br&gt;
a). Create a separate instance of the API.&lt;/p&gt;

&lt;p&gt;b). Install a routes testing library&lt;/p&gt;

&lt;p&gt;c). Write a failing test.&lt;/p&gt;

&lt;p&gt;d). Run the test.&lt;/p&gt;

&lt;p&gt;e). Make the test pass.&lt;/p&gt;

&lt;h3&gt;
  
  
  a). Create a separate instance of the API.
&lt;/h3&gt;

&lt;p&gt;An effective way to test routes of an API is to create a separate instance of the API. Create an &lt;code&gt;app.test.ts&lt;/code&gt; file and copy the content of &lt;code&gt;app.ts&lt;/code&gt; to it. Below is the code snippet.&lt;/p&gt;

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

app.test.ts


import express from "express"
import { router } from "./routes"

const api = express()

api.use(express.urlencoded({ extended: true }))
api.use(express.json())

api.use('/', router)


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  b). Install a routes testing library.
&lt;/h3&gt;

&lt;p&gt;The Supertest can be used in union with Jest to test the routes of an API. Install the Supertest module and its types using the command below.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

npm i -D supertest @types/supertest


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  c). Write a failing test.
&lt;/h3&gt;

&lt;p&gt;An example of a test for the index route can be written as shown in the code snippet below.&lt;/p&gt;

&lt;p&gt;Import required functions&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

app.test.ts
...//The previous imports go here

import request from 'supertest'
import { describe, test, expect} from '@jest/globals'


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

&lt;/div&gt;

&lt;p&gt;Write test:&lt;/p&gt;

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

app.test.ts


... //All imports go here

... //the API configurations go here

describe('Index Route', () =&amp;gt;{
    test("Responds with 200 status code", async() =&amp;gt;{
        const response = await request(api).get('/home')
        expect(response.status).toEqual(200)
    })

    test("Responds with json content", async() =&amp;gt;{
        const response = await request(api).get('/home')
        expect(response.headers['content-type']).toMatch(/json/)
    })

    test("Returns with \'welcome home\' message", async() =&amp;gt;{
        const response = await request(api).get('/home')
        expect(response.body.message).toMatch(/welcome home/i)
    })
})


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

&lt;/div&gt;

&lt;p&gt;Notice that the route we are testing does not exist in our application yet. We are doing this intentionally for this test to fail. It is good practice to have a failing test before you can write the code to make it pass. &lt;/p&gt;

&lt;h3&gt;
  
  
  d). Run the test.
&lt;/h3&gt;

&lt;p&gt;Before we run any test, remove or skip any other test file in the directory you didn't write.&lt;/p&gt;

&lt;p&gt;Now run this test using the following command to see that it fails.&lt;/p&gt;

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

npm test


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

&lt;/div&gt;

&lt;p&gt;As we see in the screenshot below, the test has failed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Ft9p3va515rc1ybh014h9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Ft9p3va515rc1ybh014h9.png" alt="Failing test"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, we make it pass in the last step.&lt;/p&gt;

&lt;h3&gt;
  
  
  e). Make the test pass.
&lt;/h3&gt;

&lt;p&gt;To make the above test pass, we first need to declare a route handler in &lt;code&gt;controller.ts&lt;/code&gt;&lt;/p&gt;

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

controller.ts


import { Request, Response } from "express";

export const home = (req: Request, res: Response) =&amp;gt;{

}

...//Other router handlers


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

&lt;/div&gt;

&lt;p&gt;Then we include the new path on the &lt;code&gt;routes.ts&lt;/code&gt; file and import the route handler.&lt;/p&gt;

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

routes.ts

import { Router } from "express";
import { home, index } from "./controller";

const router = Router()

router.get('/home', home)

router.get('/', index)

export {router}


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

&lt;/div&gt;

&lt;p&gt;Our test is still failing, let us return a response that satisfies our test from the &lt;code&gt;home&lt;/code&gt; controller function.&lt;/p&gt;

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

export const home = (req: Request, res: Response) =&amp;gt;{
    res.status(200).json({message: "Welcome home"})
}


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

&lt;/div&gt;

&lt;p&gt;With the above implementation, our test passes as shown in the screenshot below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fb0kt3kymj8alh8gt10w1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fb0kt3kymj8alh8gt10w1.png" alt="Passing test"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Success! You have written and run your fast test. In the next step, let us test a &lt;code&gt;POST&lt;/code&gt; request that saves data to the database.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Write a test involving database operation.
&lt;/h3&gt;

&lt;p&gt;We have seen how to test a simple &lt;code&gt;GET&lt;/code&gt; route that responds with a simple message. Now let us create a test for a &lt;code&gt;POST&lt;/code&gt; route    &lt;code&gt;/item&lt;/code&gt; that will do the following :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Receive input data from the user.&lt;/li&gt;
&lt;li&gt;Create a Mongoose document and save it to the database.&lt;/li&gt;
&lt;li&gt;Respond with a copy of the saved document.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We will accomplish the objective of this article in the following steps:&lt;/p&gt;

&lt;p&gt;a). Write a failing test.&lt;/p&gt;

&lt;p&gt;b). Create a model for the item.&lt;/p&gt;

&lt;p&gt;c). Declare the route handle and configure the route.&lt;/p&gt;

&lt;p&gt;d). Implement the route handler.&lt;/p&gt;

&lt;h3&gt;
  
  
  a). Write a failing test.
&lt;/h3&gt;

&lt;p&gt;The test for the route that satisfies the above requirements would look like the following.&lt;/p&gt;

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

describe('POST item', () =&amp;gt;{
    test('Responds with json content', async() =&amp;gt;{
        const response = await request(api).post('/item')
            .send({ title : 'The Book Of Scretes', pages: 800})

        expect(response.headers['content-type']).toMatch(/json/)
    })

    test('Responds with 201 status ', async() =&amp;gt;{
        const response = await request(api).post('/item')
            .send({ title : 'The Book Of Scretes', pages: 800})

        expect(response.status).toEqual(201)
    })

    test('Responds with saved document', async() =&amp;gt;{
        const response = await request(api).post('/item')
            .send({ title : 'The Book Of Secretes', pages: 800})

        expect(response.body).toHaveProperty('item')
        expect(response.body.item).toHaveProperty('_id')
        expect(response.body.item.title).toMatch(/the book of secretes/i)
        expect(response.body.item.pages).toEqual(800)
    })
})


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

&lt;/div&gt;

&lt;p&gt;All the tests we have just added are failing as evident in the screenshot below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fit8vgpf6mhtfoca5rhdk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fit8vgpf6mhtfoca5rhdk.png" alt="Failing test Involving DB"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  b). Create a model for the item.
&lt;/h3&gt;

&lt;p&gt;Before we try to make the test pass, we need to create a model that we will use to implement the database operation. Here is the code snippet for the model.&lt;/p&gt;

&lt;p&gt;To create a model, we will use the &lt;code&gt;mongoose&lt;/code&gt; module. Install mongoose using the command below.&lt;/p&gt;

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

npm i mongoose


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

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

item.model.ts


import mongoose, { HydratedDocument } from "mongoose"

interface IItem{
    title: string
    pages: number
}

type ItemModel = mongoose.Model&amp;lt;IItem&amp;gt;

const itemSchema = new mongoose.Schema&amp;lt;IItem, ItemModel&amp;gt;({
    title: String,
    pages: Number
})

export type HydratedItemDoc = HydratedDocument&amp;lt;IItem&amp;gt;
export const Item = mongoose.model&amp;lt;IItem, ItemModel&amp;gt;('Item', itemSchema)


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

&lt;/div&gt;

&lt;p&gt;Are you interested in learning how to create Mongoose models with Typescript? Be sure to check out &lt;a href="https://dev.to/ghostaram/how-to-create-mongoose-models-using-typescript-7hf"&gt;this article&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  c). Declare the route handler and configure the route.
&lt;/h3&gt;

&lt;p&gt;The model created above will help us implement a database operation within the route handler. &lt;/p&gt;

&lt;p&gt;Let us declare the route handler in &lt;code&gt;controller.ts&lt;/code&gt;&lt;/p&gt;

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

controller.ts


import { Request, Response } from "express";
import { Item } from "./item.model";

export const addNewItem = async(req: Request, res: Response) =&amp;gt;{

}

...//Previous route handlers


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

&lt;/div&gt;

&lt;p&gt;and add it to the route in &lt;code&gt;routes.ts&lt;/code&gt;.&lt;/p&gt;

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

routes.ts


import { Router } from "express";
import { addNewItem, home, index } from "./controller";

const router = Router()
router.post('/item', addNewItem)

...//previous routes


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

&lt;/div&gt;

&lt;p&gt;Remember that we reserve the implementation of the function until it is the last thing to do for the test to pass. &lt;/p&gt;

&lt;h3&gt;
  
  
  d). Implement the route handler.
&lt;/h3&gt;

&lt;p&gt;The route handler can be implemented as follows.&lt;/p&gt;

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

controller.ts


import { Request, Response } from "express";
import { Item } from "./item.model";

export const addNewItem = async(req: Request, res: Response) =&amp;gt;{
    const { title, pages } = req.body

    const item = new Item({
        title, pages
    })

    const savedItem = await item.save()

    res.status(201).json({ item: savedItem })
}

...//Previous route handlers


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

&lt;/div&gt;

&lt;p&gt;You realize the test still doesn't pass but fails with a Mongoose error. &lt;br&gt;
&lt;a href="https://media.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%2F8q00cv1lo0er288aaghs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F8q00cv1lo0er288aaghs.png" alt="Test failing with Mongoose error"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The test fails because we are not connecting to the database. However, connecting to the database will not be of great use either. Let us see how to resolve this in the coming steps.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Decouple data-access logic from the web layer.
&lt;/h2&gt;

&lt;p&gt;The first step towards resolving the issue of database errors in testing routes is to extract the database operations into a separate file. In this step, we will create a &lt;code&gt;data-access.ts&lt;/code&gt; file and move the data access logic to it as shown in the code snippet below.&lt;/p&gt;

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

data-access.ts


import { IItem, Item } from "./item.model";

export const createNewItem = async(data: IItem) =&amp;gt;{
    const item = new Item({
        title: data.title, 
        pages: data.pages
    })

    const savedItem = await item.save()
}


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

&lt;/div&gt;

&lt;p&gt;Then we call the function in the route handler.&lt;/p&gt;

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

import { Request, Response } from "express";
import { createNewItem } from "./data-access";

export const addNewItem = async(req: Request, res: Response) =&amp;gt;{
    const { title, pages } = req.body

    const savedItem = await createNewItem({ title, pages })

    res.status(201).json({ item: savedItem })
}


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

&lt;/div&gt;

&lt;p&gt;With that, we are two steps closer to resolving the problem. Let's introduce dependencies on the router and the controller in the next step.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Introduce dependencies on the controller and the router.
&lt;/h2&gt;

&lt;p&gt;The point of introducing dependencies is to allow us to replace the data-access layer with mocks. &lt;/p&gt;

&lt;p&gt;The easiest way to introduce dependencies in a file with related functions is to encapsulate all of them in a class. If the file consists of related function calls, we encapsulate them inside one function.&lt;/p&gt;

&lt;p&gt;In this step, we will do the following activities:&lt;/p&gt;

&lt;p&gt;a). Encapsulate the data access layer.&lt;/p&gt;

&lt;p&gt;b). Encapsulate the controller (web layer).&lt;/p&gt;

&lt;p&gt;c). Encapsulate the router.&lt;/p&gt;

&lt;p&gt;d). Refactor the main file and the test file.&lt;/p&gt;

&lt;h3&gt;
  
  
  a). Encapsulate the data access layer.
&lt;/h3&gt;

&lt;p&gt;We will first encapsulate the data access layer. We will create a class called &lt;code&gt;APIDAL&lt;/code&gt; - API data access layer - to encapsulate database operations.&lt;/p&gt;

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

import { IItem, Item } from "./item.model";

export class APIDAL{
    public createNewItem = async(data: IItem) =&amp;gt;{
        const item = new Item({
            title: data.title, 
            pages: data.pages
        })

        const savedItem = await item.save()

        return ({
            title: savedItem.title,
            pages: savedItem.pages,
            _id: savedItem._id,
            id: savedItem.id
        })
    }
}


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  b). Encapsulate the controller.
&lt;/h3&gt;

&lt;p&gt;We will create a class called &lt;code&gt;APIController&lt;/code&gt; to encapsulate the controller functions. The &lt;code&gt;APIController&lt;/code&gt;  constructor accepts an object of the data-access layer class as a dependency.&lt;br&gt;
Below is the code snippet.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

controllers.ts

import { Request, Response } from "express";
import { APIDAL } from "./data-access";

export class APIController{
    private dal: APIDAL

    constructor(dataAccessLayer: APIDAL){
        this.dal = dataAccessLayer
    }
    public addNewItem = async(req: Request, res: Response) =&amp;gt;{
        const { title, pages } = req.body

        const savedItem = await this.dal.createNewItem({ title, pages })

        res.status(201).json({ item: savedItem })
    }

    public home = (req: Request, res: Response) =&amp;gt;{
        res.status(200).json({message: "Welcome home"})
    }
    public index = (req: Request, res: Response) =&amp;gt;{
        res.status(200).json({ message: 'Welcome to my API' })
    }
}


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  c). Encapsulate the router.
&lt;/h3&gt;

&lt;p&gt;Our routes file consists of function calls. Therefore, we will encapsulate them in one function called &lt;code&gt;apiRouter&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import { Router } from "express";
import { APIController} from "./controller";

const apiRouter = (controller: APIController) =&amp;gt; {
    const router = Router()
    router.post('/item', controller.addNewItem)

    router.get('/home', controller.home)

    router.get('/', controller.index)

    return router

}
export {apiRouter}


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  d). Refactor the main file and the test file.
&lt;/h3&gt;

&lt;p&gt;The above changes force us to change how we call the &lt;code&gt;router&lt;/code&gt; in &lt;code&gt;app.ts&lt;/code&gt; and &lt;code&gt;app.test.ts&lt;/code&gt;. Here are the updates.&lt;/p&gt;

&lt;p&gt;Main file.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

app.ts

import express from "express"
import { apiRouter } from "./routes"
import { APIController } from "./controller"
import { APIDAL } from "./data-access"

const apiDAL = new APIDAL()
const controller = new APIController(apiDAL)
const api = express()

api.use(express.urlencoded({ extended: true }))
api.use(express.json())

api.use( apiRouter(controller))


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

&lt;/div&gt;

&lt;p&gt;Test File.&lt;/p&gt;

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

api.test.ts

...// Previous imports

import { apiRouter } from "./routes"
import { APIController } from "./controller"
import { APIDAL } from "./data-access"

const apiDAL = new APIDAL()
const controller = new APIController(apiDAL)
const api = express()

api.use(express.urlencoded({ extended: true }))
api.use(express.json())

api.use( apiRouter(controller))

...//Tests


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

&lt;/div&gt;

&lt;p&gt;Lastly, we replace the data access layer with a mock class. In the next section, let's create a mock class for the data access layer and import it into the test file.&lt;/p&gt;

&lt;h3&gt;
  
  
  8. Mock your data access layer.
&lt;/h3&gt;

&lt;p&gt;Do you remember when we said we would not test the database operations? We meant to replace the database operations with fake functions. &lt;/p&gt;

&lt;p&gt;In this step, we will create a new class with a function that imitates the one in the &lt;code&gt;APIDAL&lt;/code&gt; class. We will create the file and the class with the same names in a different directory.&lt;/p&gt;

&lt;p&gt;Here are the steps we will follow.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a subdirectory directory called &lt;code&gt;mocks&lt;/code&gt; within the &lt;code&gt;src&lt;/code&gt; directory.&lt;/li&gt;
&lt;li&gt;Create a file called &lt;code&gt;data-access.ts&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Create the &lt;code&gt;APIDAL&lt;/code&gt; class on the file and copy-paste the code snippet below.&lt;/li&gt;
&lt;/ul&gt;

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

 import { IItem, Item } from "../item.model";

export class APIDAL{
    public createNewItem = jest.fn(async(data: IItem) =&amp;gt;{
        const item = new Item({
            title: data.title, 
            pages: data.pages
        })

       return ({
            title: item.title,
            pages: item.pages,
            _id: item._id,
            id: item.id
        })
    })
}


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

&lt;/div&gt;

&lt;p&gt;In the above code snippet, we have replaced the original function implementation with a mock.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Replace the data access layer with the mock in the test file.
&lt;/h2&gt;

&lt;p&gt;After creating a mock for the data access layer, we import it into the test files as shown in the code snippet below.&lt;/p&gt;

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

app.test.ts


...//Previous imports are here

import { apiRouter } from "./routes"
import { APIController } from "./controller"
import { APIDAL } from "./mocks/data-access" //Imported mock class

const apiDAL = new APIDAL()
const controller = new APIController(apiDAL)
const api = express()

api.use(express.urlencoded({ extended: true }))
api.use(express.json())

api.use( apiRouter(controller))

...//All the written tests are below here


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

&lt;/div&gt;

&lt;p&gt;Now run your tests. They should all pass as shown in the screenshot below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Ffulpyivo0b8nui3tmj1h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Ffulpyivo0b8nui3tmj1h.png" alt="All tests passing"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Finally, we have successfully explored and practiced how to test Express API routes the easy way. In this article we have learned how to do the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Separate unit test from the main application.&lt;/li&gt;
&lt;li&gt;Modularize an Express application for easy testing.&lt;/li&gt;
&lt;li&gt;Write unit tests for routes of an Express application.&lt;/li&gt;
&lt;li&gt;Test routes involving database operations.&lt;/li&gt;
&lt;li&gt;Run unit tests without connecting to the database or running your application on a dev server.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The code we have written in this article is available in &lt;a href="https://github.com/GHOST-Aram/api-testing-the-easy-way" rel="noopener noreferrer"&gt;this GitHub repository&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Configuring Jest for Typescript Unit Tests</title>
      <dc:creator>Felix Owino</dc:creator>
      <pubDate>Sat, 18 Nov 2023 08:02:46 +0000</pubDate>
      <link>https://forem.com/ghostaram/configuring-jest-for-typescript-unit-tests-4iag</link>
      <guid>https://forem.com/ghostaram/configuring-jest-for-typescript-unit-tests-4iag</guid>
      <description>&lt;p&gt;Jest is a unit testing library for JavaScript. Testing JavaScript code with Jest is straightforward and doesn't require any additional configuration. When testing Typescript code without compiling it to JavaScript first, a few configurations are required. There are two ways for setting up Jest for Typescript unit test; via Babel or &lt;code&gt;ts-jest&lt;/code&gt;. Babel is a popular multipurpose transpiler for JavaScript. &lt;code&gt;ts-jest&lt;/code&gt; is an extension of the Typescript compiler tailored to work with Jest. In this article, we will explore and demonstrate how to configure Jest to test Typescript code via &lt;code&gt;ts-jest&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To create a Typescript and Jest testing environment, we will execute the following sequence of activities:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create an initialized working directory.&lt;/li&gt;
&lt;li&gt;Install Typescript.&lt;/li&gt;
&lt;li&gt;Configure Typescript.&lt;/li&gt;
&lt;li&gt;Install Jest and its related dependencies.&lt;/li&gt;
&lt;li&gt;Configure Jest for Typescript.&lt;/li&gt;
&lt;li&gt;Edit &lt;code&gt;package.json&lt;/code&gt; test script.&lt;/li&gt;
&lt;li&gt;Try it out.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let us start by creating an npm-initialized working directory.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Create an initialized working directory.
&lt;/h2&gt;

&lt;p&gt;In this step, we will create a directory called &lt;code&gt;jest-ts-tests&lt;/code&gt; and initialize it as a node project directory.&lt;/p&gt;

&lt;p&gt;Create a directory named &lt;code&gt;ts-jest-env&lt;/code&gt; and run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm init 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to generate &lt;code&gt;package.json&lt;/code&gt; file&lt;/p&gt;

&lt;p&gt;By executing the above instructions, we now have a directory ready for use. Let us go and install Typescript in the next step.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Install Typescript
&lt;/h2&gt;

&lt;p&gt;In the previous step, we created a directory for us to work on. In this step, we will install Typescript as a development dependency as follows.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Run npm i -D typescript
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have successfully installed Typescript, let us configure it in the next step.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Configure Typescript
&lt;/h2&gt;

&lt;p&gt;We will install ready-to-use Typescript base configurations instead of starting from scratch. In this article, we will use Typescript base configurations for node version 20. If you are using a different version of node, visit the &lt;a href="https://github.com/tsconfig/bases"&gt;tsconfig bases&lt;/a&gt; docs to find out what you need. You can also create a Typescript configuration file with settings that work for you.&lt;/p&gt;

&lt;p&gt;Run the following command to install base Typescript configurations for node version 20.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i -D @tsconfig/node20
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a &lt;code&gt;tsconfig.json&lt;/code&gt; file and paste the following configs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "extends": "@tsconfig/node20/tsconfig.json",
  "$schema": "https://json.schemastore.org/tsconfig",
  "display": "Node 20",
  "_version": "20.1.0",

  "compilerOptions": {
    "lib": ["es2023"],
    "module": "node16",
    "target": "es2022",

    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "moduleResolution": "node16",
    "outDir": "./build",
    "rootDir": "./src"
  },
  "include": ["src/**/*.ts"]
}

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Install Jest and related dependencies.
&lt;/h2&gt;

&lt;p&gt;We are now ready to write Typescript code. In this step, we will install Jest and all the necessary dependencies related to it.&lt;/p&gt;

&lt;p&gt;Run the following command to install Jest and the other dependencies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i -D jest ts-jest @types/jest @jest/globals
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need &lt;code&gt;ts-jest&lt;/code&gt; to compile Typescript for Jest and &lt;code&gt;@jest/globals&lt;/code&gt; to provide Jest global global utilities for typescript. &lt;/p&gt;

&lt;h2&gt;
  
  
  5. Configure Jest for Typescript
&lt;/h2&gt;

&lt;p&gt;Here, we tell Jest to execute &lt;code&gt;.ts&lt;/code&gt; files with &lt;code&gt;ts-jest&lt;/code&gt;. To complete this configuration, we will generate a Jest configuration file with &lt;code&gt;ts-jest&lt;/code&gt; presets using the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx ts-jest config:init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Executing the above command generates a &lt;code&gt;jest.config.js&lt;/code&gt; file with &lt;code&gt;ts-jest&lt;/code&gt; as a preset. &lt;/p&gt;

&lt;p&gt;Well done, let us edit our npm test scripts in the next step.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Edit &lt;code&gt;package.json&lt;/code&gt; test script.
&lt;/h2&gt;

&lt;p&gt;We want to be able to run tests easily by using a simple npm command. To enable the command, edit the &lt;code&gt;scripts&lt;/code&gt; object of &lt;code&gt;package.json&lt;/code&gt; as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; "scripts": {
    "test": "jest --watch",
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The setting above allows us to run tests using the &lt;code&gt;npm test&lt;/code&gt; command. The &lt;code&gt;--watch&lt;/code&gt; flag tells Jest to run tests every time our code changes.&lt;/p&gt;

&lt;p&gt;Next, we proceed to the actual testing to find and verify our configurations.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Try it out.
&lt;/h2&gt;

&lt;p&gt;Up to this point, we have installed all the required dependencies for testing Typescript with Jest. Here, we will write a simple function and test it to verify that our configurations are on point.&lt;/p&gt;

&lt;p&gt;Create an &lt;code&gt;index.ts&lt;/code&gt; file and export a simple function that you want to test. Do not finish the implementation of the function until you write a failing test.&lt;/p&gt;

&lt;p&gt;For example: A &lt;code&gt;sum&lt;/code&gt; function,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export const sum(num1: number, num2: number): number =&amp;gt;{

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

&lt;/div&gt;



&lt;p&gt;Create &lt;code&gt;index.test.ts&lt;/code&gt; and import &lt;code&gt;sum&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;index.test.ts

import {sum} from `index`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Import Jest globals.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;index.test.ts

import {sum} from `index`
import { describe, test, expect } from "@jest/globals"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Write test.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;index.test.ts

import {sum} from `index`
import { describe, test, expect } from "@jest/globals"

describe('Sum function', () =&amp;gt;{
    test('Returns correct value', () =&amp;gt;{
        expect(sum(2, 3)).toEqual(5)
    })
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the following command to begin your tests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Edit your &lt;code&gt;sum&lt;/code&gt; function until your test passes. &lt;/p&gt;

&lt;p&gt;Congratulations! That's the end of configuring Jest for Typescript unit tests. We have created a working test environment for testing  Typescript code using Jest and ts-jest. The resultant directory is available on &lt;a href="https://github.com/GHOST-Aram/ts-jest-env"&gt;this GitHub repository&lt;/a&gt;. If you are interested in learning other ways of testing typescript code with Jest, feel free to visit the document on &lt;a href="https://jestjs.io/docs/getting-started#using-typescript"&gt;using Jest with typescript&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>typescript</category>
      <category>unittest</category>
    </item>
    <item>
      <title>Hashing and Verifying Passwords in Mongoose Schema</title>
      <dc:creator>Felix Owino</dc:creator>
      <pubDate>Thu, 16 Nov 2023 09:22:25 +0000</pubDate>
      <link>https://forem.com/ghostaram/hashing-and-verifying-passwords-in-mongoose-schemas-pl3</link>
      <guid>https://forem.com/ghostaram/hashing-and-verifying-passwords-in-mongoose-schemas-pl3</guid>
      <description>&lt;p&gt;Are you creating a web application that is going to require users to sign in with passwords? It's a good security measure to store passwords in the database as hashed strings instead of plain strings. Hashing passwords is done to protect users' passwords. In case an attacker gains access to your database, they will see the hashed passwords but they won't be able to use them. &lt;/p&gt;

&lt;p&gt;In this article, we will learn how to create a user schema that hashes users' passwords before saving them to the database. We will also learn how to add an instance method to the schema that verifies user passwords during login.&lt;/p&gt;

&lt;p&gt;We will not cover other surrounding topics such as user authentication and user registration middleware in this article. The main goal of this article is to show you how to create a self-contained schema. This schema will make it easy for you to implement user registration and authentication middleware without worrying about password hashing.&lt;/p&gt;

&lt;p&gt;We will use Typescript in this article. This article does not go into depth about how to create models and schema with Mongoose and Typescript. Therefore, this article assumes that you know how to create Mongoose schema using Typescript. If you are new to using Typescript, visit this &lt;a href="https://dev.to/ghostaram/how-to-create-mongoose-models-using-typescript-7hf"&gt;article on creating Mongoose schema with Typescript&lt;/a&gt; before continuing.&lt;/p&gt;

&lt;p&gt;Before we dive into coding, let us list out the procedure we are going to follow.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Initialize a working directory and configure Typescript.&lt;/li&gt;
&lt;li&gt;Create the user schema.&lt;/li&gt;
&lt;li&gt;Implement password hashing.&lt;/li&gt;
&lt;li&gt;Implement password Verification.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let us start by creating a working directory.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Initializing working directory and configure Typescript.
&lt;/h2&gt;

&lt;p&gt;In this step, we will &lt;a href="https://github.com/GHOST-Aram/node-ts-starter" rel="noopener noreferrer"&gt;clone a pre-configured working directory from GitHub&lt;/a&gt;. You can also create your own directory with configurations of your choice. If you need help, see &lt;a href="(https://dev.to/ghostaram/initializing-project-directory-for-node-and-typescript-1f8e)"&gt;how to set up an initial project directory for Node and Typescript&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Your working directory should have something looking like this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fepwug6e69rwyt1307nb1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fepwug6e69rwyt1307nb1.png" alt="Initial working directory"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After successfully cloning the repository, install its dependencies using the following command:&lt;/p&gt;

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

npm install


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

&lt;/div&gt;

&lt;p&gt;With the working directory set up, let us create the user schema.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Creating the user schema.
&lt;/h2&gt;

&lt;p&gt;To create a Mongoose schema, we need to install &lt;code&gt;mongoose&lt;/code&gt; and import it to our models file. &lt;/p&gt;

&lt;p&gt;Install mongoose using the following command:&lt;/p&gt;

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

npm install mongoose


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

&lt;/div&gt;

&lt;p&gt;Create the &lt;code&gt;User.model.ts&lt;/code&gt; file in the &lt;code&gt;src&lt;/code&gt; directory of your project and import Mongoose.&lt;/p&gt;

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

import mongoose from "mongoose"


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

&lt;/div&gt;

&lt;p&gt;Create an interface for the raw document as created in the code snippet below.&lt;/p&gt;

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

interface IUser{
    first_name: string,
    last_name: string,
    password: string,
    username: string
}


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

&lt;/div&gt;

&lt;p&gt;Create the user schema that implements the interface as created in the code snippet below.&lt;/p&gt;

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

const userSchema = new mongoose.Schema&amp;lt;IUser&amp;gt;({
    first_name: String,
    last_name: String,
    password: String,
    username: String
})


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

&lt;/div&gt;

&lt;p&gt;Now we have successfully created a user schema, let's add password hashing logic in step 3.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Implement password hashing.
&lt;/h2&gt;

&lt;p&gt;In the last step, we implemented a simple user schema. Here, we will add a functionality that will hash every password entered by the user before saving. &lt;/p&gt;

&lt;p&gt;To add a logic that is executed before saving a document, we use the &lt;code&gt;pre&lt;/code&gt; hook of the Mongoose &lt;code&gt;Schema&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We will use the &lt;code&gt;bcrypt&lt;/code&gt; module to hash user passwords. Install the &lt;code&gt;bcrypt&lt;/code&gt; module and its types using the following commands.&lt;/p&gt;

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

npm install bcrypt
npm install -D @types/bcrypt


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

&lt;/div&gt;

&lt;p&gt;Import the &lt;code&gt;hash&lt;/code&gt; function from &lt;code&gt;bcrypt&lt;/code&gt; as follows.&lt;/p&gt;

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

import { hash } from 'bcrypt'


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

&lt;/div&gt;

&lt;p&gt;The following code snippet shows how the password hashing on save can be implemented on the schema.&lt;/p&gt;

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


userSchema.pre('save', async function(next){

    const hashedPassword =  await hash(this.password, 10)
    this.password = hashedPassword

    next()
})


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

&lt;/div&gt;

&lt;p&gt;The above code snippet does the following:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Convert the raw password into a hash string. &lt;/li&gt;
&lt;li&gt;Replace the original raw password with the hashed password.&lt;/li&gt;
&lt;li&gt;Call the  &lt;code&gt;next&lt;/code&gt; callback function. The callback signals Mongoose that we are done hashing the password and it can now be saved to the database.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is important not to assume the pre save hook to work across every database operation. The pre save hook only encrypts the password on the initial creation. The pre save hook is not invoked by any other database operation that does not call the save method. This means that an update operation will not invoke the password encryption function at all. If you want to change your password, you have to encrypt it in a separate program otherwise it will be stored in the database as plain text.&lt;/p&gt;

&lt;p&gt;At this point, we are done with the password hashing functionality. Let us add an instance method to verify passwords in the next step.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Implement password verification.
&lt;/h2&gt;

&lt;p&gt;In the previous section, we added password hashing to our schema. In this section, we will add a password verification method to the user schema. &lt;/p&gt;

&lt;p&gt;Before adding the method to the schema, we need to create an interface for instance methods. The following code snippet shows the declaration of the interface with the signature for the verification function.&lt;/p&gt;

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

interface UserMethods{
    isValidPassword:(password: string) =&amp;gt; Promise&amp;lt;boolean&amp;gt;
}


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

&lt;/div&gt;

&lt;p&gt;Next, we need to add the interface to the &lt;code&gt;Schema&lt;/code&gt; constructor and &lt;code&gt;Model&lt;/code&gt; type as follows.&lt;/p&gt;

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

type UserModel = Model&amp;lt;IUser,{}, UserMethods&amp;gt;

const userSchema = new mongoose.Schema&amp;lt;IUser, UserModel, UserMethods&amp;gt;({
    first_name: String,
    last_name: String,
    password: String,
    username: String
})


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

&lt;/div&gt;

&lt;p&gt;Finally, we implement the &lt;code&gt;isValidPassword&lt;/code&gt; method as follows:&lt;/p&gt;

&lt;p&gt;Import the &lt;code&gt;compare&lt;/code&gt; function and implement the method.&lt;/p&gt;

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

import { compare } from 'bcrypt'


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

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

userSchema.method('isValidPassword', async function(
    password: string): Promise&amp;lt;boolean&amp;gt;{
    const isValid = await compare(password, this.password)
    return isValid
})


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

&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;isValidPassword&lt;/code&gt; method will be accessible through the user document. In the implementation of authentication, the method &lt;code&gt;isValidPassword&lt;/code&gt; can be called on the user document. The method returns a promise. The promise resolves to true or false depending on whether the user entered the correct password or not.&lt;/p&gt;

&lt;p&gt;Export the model as follows.&lt;/p&gt;


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

&lt;p&gt;export const User = model&amp;lt;IUser, UserModel&amp;gt;('User', userSchema)&lt;/p&gt;

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

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Conclusion&lt;br&gt;
&lt;/h2&gt;

&lt;p&gt;Finally, we have learned how to create a self-contained user schema. The schema can convert a password into a hash string before saving it to the database. The schema can also verify user passwords against the stored hashed passwords during authentication. Visit &lt;a href="https://dev.to/ghostaram/how-to-create-mongoose-models-using-typescript-7hf"&gt;this article&lt;/a&gt; to learn more about creating Mongoose models with Typescript.&lt;/p&gt;

</description>
      <category>node</category>
      <category>javascript</category>
      <category>typescript</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
