Tutorials on Front End

Learn about Front End from fellow newline community members!

  • React
  • Angular
  • Vue
  • Svelte
  • NextJS
  • Redux
  • Apollo
  • Storybook
  • D3
  • Testing Library
  • JavaScript
  • TypeScript
  • Node.js
  • Deno
  • Rust
  • Python
  • GraphQL
  • React
  • Angular
  • Vue
  • Svelte
  • NextJS
  • Redux
  • Apollo
  • Storybook
  • D3
  • Testing Library
  • JavaScript
  • TypeScript
  • Node.js
  • Deno
  • Rust
  • Python
  • GraphQL

How to use urql authExchange to implement authentication in Next.js

In this article, we will learn how to use the urql authExchange to add authentication with a GraphQL API in a Next.js app.In the last article , we have learnt how to use urql to execute queries and mutations in a Next.js Server-Side Rendered app. In the following sections, we will recap those learnings and build on them to implement authentication using urql exchanges. urql is a lightweight, versatile and extensible GraphQL client for modern frontend apps, with support for React, Svelte, Vue and plain JavaScript. It was introduced as an alternative to existing GraphQL clients like Relay and Apollo . Every query or mutation in urql is modeled as an 'operation', and the system at any moment has a stream of operations issued by various parts of the app. Exchanges are pieces of middleware that transform the stream of operations into a stream of results. This is explained in more detail in the architecture documentation . Some of urql 's core features such as fetching data and caching are also handled via exchanges implemented by the urql team and provided by default. You can also create your own exchanges by implementing functions that conform to the rules defined here . Next.js requires Node to be pre-installed on your system. You can then scaffold a Next.js TypeScript app using the following command in your terminal/command prompt. Once you have a skeleton app set up, you can install the dependencies required for urql . graphql is a peer dependency of urql and provides the underlying GraphQL implementation. No additional type definitions are required since urql is written in TypeScript. next-urql provides the Next.js bindings for urql . react-is is a peer dependency of next-urql , required for react-ssr-prepass to walk the component tree and pre-fetch any data required for rendering. @urql/exchange-auth provides the authExchange that we will implement our API authentication with. Finally, jwt-decode will be used to read the token and determine expiration time. We will also use Material UI to quickly scaffold out a login/register component and one that renders user info. Let us install the required dependencies for Material UI. Let us use the withUrqlClient HOC to wrap our entire app in the urql context. This makes the urql client and hooks usable in the rest of our app. The first parameter to withUrqlClient is a function that returns a ClientOptions object. This can be used to pass configuration into the urql client instance, such as the API URL, custom fetch function, request policy and any additional middleware in the exchanges property. For this tutorial, we will use the Web Collections Demo API from Formidable. In this tutorial, we will build a simple app with two screens - a login/register screen where users will authenticate or sign up to the app, and a user info screen that displays information about the logged in user. We will use the following operations from the Web Collections Demo API: We will use the browser's local storage to persist tokens across page reloads. The authExchange is a piece of middleware for the urql client, which intends to facilitate the typical JSON Web Token (JWT) based authentication flow with a simple and flexible API. It is provided in the @urql/exchange-auth package. We can add the authExchange to the exchanges property when configuring our urql client. The authExchange itself takes four pieces of configuration: The signin , register and refreshCredentials mutations from our API return an object that has the following shape. Let us implement a small helper function that stores the auth state in the browser's local storage. We've added a check for window since we only want this code to run in the browser. When the user logs out, we'd like to clear the auth state from storage. We can now add a couple of convenience functions to fetch the token and refresh token. Let us start implementing the authExchange functions, beginning with getAuth - this function needs to handle a couple of different scenarios: The addAuthToOperation function receives two parameters - the first is the current authState , and the second is the operation that will be executed next. The second parameter is of type Operation and is urql's way of representing an item in the stream of GraphQL requests. Operations have a context that contains the fetch options, either as an object or as an initializer function. We will retrieve the options for the current operation like so. We'll then create a new operation which is basically a clone of the input operation, along with our required override - the addition of our access token to the Authorization header. So the entire implementation of the addAuthToOperation function will look like this: Our API uses the GraphQL error code extension to communicate errors. For the purposes of this tutorial, we will only consider UNAUTHORIZED errors. Token expiry is one of the scenarios when we know the API will error. We are able to determine this by decoding the JWT and reading the exp field which specifies the expiration time. Our API's access token specifies the expiration time as seconds since the Unix epoch. Let us add a buffer of 5 seconds to determine that the token is about to expire. Now, this would work if all of our queries and mutations required the access token to be provided. However, we have mutations such as login and register which do not require the token passed in. We will need to adapt our logic to account for these mutations, and this can be done using the passed in Operation object. The full implementation of the willAuthError function will be as follows. Now that we have implemented all the required functions, the final step is to configure the urql client with the authExchange . Let us create a factory function that receives the ssrExchange and returns a client configuration object. We'll use this on our app's homepage in the next section. Our home page will render the login form when unauthenticated, and a user profile when the user is logged in. We'll use our clientOptions factory function here to provide the urql client to our app. We'll use two mutations login and register from the API in this component. urql 's useMutation hook can be used to consume these mutations within a React component. The useMutation hook returns a tuple containing the current state of the operation, and a function that triggers it. We'll trigger our mutations on submission of the respective form. Here is the full implementation of the page. We'll use the me query from the API to retrieve the user's ID, name and creation time. We can then use urql 's useQuery hook to execute the query. Let us create a simple layout with material-ui components to display the profile data. This will also include a loading indicator and an alert to show any error messages. In this article, we have learnt how to implement JWT authentication with a GraphQL API using urql and @urql/exhange-auth with a Next.js app. We have understood how to apply authentication to queries and mutations, and built a simple app that allows login and registration. All the code used in this article is available on my GitHub .

Thumbnail Image of Tutorial How to use urql authExchange to implement authentication in Next.js

The newline Guide to Modernizing an Enterprise React App is Now Live!🎉

Creating large, long-lived React apps, such as those required in large enterprises, poses unique challenges. Most developers lack the knowledge of how to build apps that scale gracefully and use the latest React techniques, such as React Hooks and React Testing Library, to modernize React apps in the enterprise. This course will help you master React development in the context of building for large enterprises. You will learn the latest React syntax, React Hooks, and more as you build an actual enterprise React app. You will learn: In  The newline Guide to Modernizing an Enterprise React App,  we teach you the various aspects of React development that ensure that apps vital to a company's success keep running. This is based on years of experience building and maintaining large-scale, complex, React apps in production, and will prepare you to do the same for any enterprise. By the end of the first module in the course, you'll already have started working with the sample enterprise React app, Hardware Handler, and preparing to modernize it using the latest React standards. The subsequent modules will teach you important React concepts and guide you in modernizing this React app, including: Paige Niedringhaus  is your instructor for this course. She's a Staff Software Engineer for the Internet Of Things startup, Blues Wireless, which has backing from leading investors, including Sequoia Capital and Microsoft founder Bill Gates. Paige has a strong background in React and large-scale enterprise apps, having worked in software engineering for The Home Depot for 5 years. Now she teaches you everything you need to build beautiful apps with React in a way that can support the mission-critical demands of large enterprises. You can read more details about the course over at the Modernizing An Enterprise React App website  

Thumbnail Image of Tutorial The newline Guide to Modernizing an Enterprise React App is Now Live!🎉

I got a job offer, thanks in a big part to your teaching. They sent a test as part of the interview process, and this was a huge help to implement my own Node server.

This has been a really good investment!

Advance your career with newline Pro.

Only $30 per month for unlimited access to over 60+ books, guides and courses!

Learn More

Cypress Studio - the underrated feature speeding up e2e testing

Testing is basically a requirement for modern software today, not a nice-to-have. In the past, end-to-end testing was hard to set up, flaky, and generally a pain to deal with, but it's the best automated testing option to confirm software works. Cypress.io continues to improve the e2e testing experience and its new feature Cypress Studio takes it a step further to make writing tests quicker and easier too.Photo by Farzad Nazifi on Unsplash When Cypress.io first hit the scene in 2015, it made a splash because it fixed so many of the issues that existed with other end-to-end testing (e2e) competitor frameworks. Between good documentation, intuitive syntax, improved debugging, and no reliance on Selenium under-the-hood - everything about Cypress was a major step forward for e2es, but it wasn't content just to stop there. The team behind Cypress regularly keeps releasing new features and functionality to make it more and more useful for devs, and make e2e testing (traditionally kind of a pain) easier and easier as well. One recent release that's currently tucked behind a feature flag is called Cypress Studio , and it's an absolute game changer. Today, I'll show you how to add Cypress to an existing JavaScript project, enable Cypress Studio, and let it help do the heavy lifting of writing end-to-end tests. It's such a cool feature to help dev teams save time on testing, deliver new features faster, and still ensure the mission critical functionality of the app continues to work as expected. Although Cypress is kind enough to provide a host of sample scripts to show many of its features in action, it really shines with a local app to test against, and I just so happen to have one that fits the bill. The app I'm using is a React-based movie database that allows users to see upcoming movies and movies in theaters now, browse movies by genre, and search for movies by title. This will be a good app to demonstrate Cypress Studio's power. Once we've got an app to add Cypress to, the first thing we'll need to do is download Cypress to it. This is another reason Cypress stands head and shoulders above its competitors: one npm download gives you all the tools you need to start writing e2es. No dev dependencies, no extra libraries with mismatched package versions, none of that nonsense to deal with. At the root of your project, where your package.json  file lives, run the following command from the terminal: This will add a bunch of new Cypress-based folders and files to your app, and with just a few small configuration changes we'll be ready to go. See all those new folders under cypress/ ? That's what you should see after initial installation. For ease of use, I like to add npm scripts for the two main Cypress commands we'll be using: In your package.json  file, add the following two lines in your "scripts"  section. Now when we need to run the tests, a simple npm run cy:run  or npm run cy:open , straight from the command line, will do the trick.  Ok, before we get to writing our own tests, let's run the pre-populated tests in Cypress to get familiar with the its Test Runner. From your command line, run the following shell command: This should open the Cypress Test Runner, and from here, click the Run integration spec button in the top right hand corner to run through all the pre-made tests once. After all the Cypress tests run and pass, we're ready to delete them and get to work on our own tests for our app. Go ahead and clear all the files out of the Cypress folders of fixtures/ and  integration/ . You'll probably also want to add the folders of cypress/screenshots/  and cypress/videos/  to your .gitignore  file just so you don't commit those screenshots and videos that Cypress automatically takes during test runs to your GitHub repo (unless you want to, of course). Add baseUrl variable With that taken care of, let's set up a baseUrl  in our cypress.json file and enable Cypress Studio there too. Turn on experimentalStudio To enable Cypress studio, just add "experimentalStudio": true  to our cypress.json  file. So here's what the cypress.json  file will end up with. Now we can write our first test file and test. Inside of the cypress/integration/  folder in your project, create a new test file named movie-search-spec.js . This folder is where Cypress will look for all your e2e test files when it runs. Give it a placeholder test: we have to tell Cypress where we want it to record the test steps we're going to show it. So just create a typical describe  test block and inside of that, create an it  test. A good first test would be to test that a user can navigate to the movie search option, search for a particular movie name, and click into the results based on that search. Here's what my empty testing placeholder looks like in the movie-search-spec.js  file. I think we're about ready to go. One thing you must do before starting up Cypress to run tests against your local app is to start the app locally. For Cypress, it's an anti-pattern to start the app from a test, so just fire it up in a separate terminal, then open up the Cypress Test Runner. Start the movie app In one terminal run our movie app: Start the Cypress Test Runner And in a second terminal, open the Cypress Test Runner: In Cypress, Add Commands to Test When the Cypress Test Runner is open, enter our test file and click the tiny blue magic wand that says  Add Commands to Test  when you hover over it. And from here, go for it - test the app. For me, I clicked the Movie Search link in the nav bar, typed "Star Wars" into the search box, clicked into one of the results, etc. When you're satisfied with what your test is doing, click the Save Commands button at the bottom of the test, and Cypress will run back through all the commands it's just recorded from your actions. Tell me that's not cool. If you go back to your IDE now, you'll see all the actions Cypress recorded, along with a few comments to tell you it was Cypress generating the code and not a developer. This is what my test now looks like: Just wow, right? Although our test is good, Cypress can't be expected to test for all the things a developer might know are important. Things like the number of movies returned from searching "star wars" or checking the title of the movie being clicked into and the contents inside of the movie page itself. I'll fill in some of those details myself now.  If you look at my code above, I added comments after the extra assertions I added - mainly small things like checking for search text, the count of movies returned, the movie info like rating and release date in this specific movie. I didn't add a ton of extra code, just a few extra lines of details. Now run the test again and check the results. And we're done! Congrats - our first Cypress Studio-assisted e2e test is written.  Just repeat these steps for as many end-to-end tests as you need to write and prepare to be amazed at how much time it saves you. In modern software, testing is a critical piece of any solid enterprise application. It helps ensure our app continues to function as expected while adding new functionality, and end-to-end testing is the closest we can get to mimicking exactly how a user would use the app with automation. Cypress broke the mold of what e2e testing frameworks are capable of when it debuted back in 2015, and it's only continued to improve with time. My favorite new feature of late is the ability to show  Cypress how a test should act instead of writing it yourself with Cypress Studio - the time saving possibilities are immense. And more time saved means finishing features faster and getting new functionality into the hands of users quicker. Win win win. In 10 modules and 54 lessons, I cover all the things I learned while at The Home Depot, that go into building and maintaining large, mission-critical React applications - because it's so much more than just making the code work. From tooling and refactoring, to testing and design system libraries, there's a ton of material and hands-on practice here to prepare any React developer to build software that lives up to today's high standards. I hope you'll check it out.

Thumbnail Image of Tutorial Cypress Studio - the underrated  feature speeding up e2e testing

Why should I care about abstract syntax trees as a frontend engineer?

You may have seen the term "abstract syntax trees", "AST", or maybe even learned about them in a computer science curriculum, but chalked them up as being irrelevant to the work you need to do as a frontend engineer. On the contrary, abstract syntax trees are ubiquitous in the frontend ecosystem. Understanding abstract syntax trees isn't a requirement for being a productive or successful frontend engineer, but it can unlock a new skill set that has many practical applications in frontend development. First, what are abstract syntax trees? In the simplest form, an abstract syntax tree is a way to represent code so a computer can understand it. The code we write is a giant string of characters that will only do something if a computer can understand and interpret the code. An abstract syntax tree is a  tree data structure . A tree data structure starts with a root value. The root can then point to other values, and those values to others, and so on. This begins to create an implicit hierarchy, and also happens to be a great way to represent source code in a way computers can easily interpret. For example, say we had the code snippet  2 + (4 * 10) . To evaluate this code, multiplication is performed first, followed by addition. Since the addition is the last thing to happen or the highest in this hierarchy it will be the root. It then points to two other values, on the left is the number 2 , but on the right is another equation. This time it's multiplication, and it also has two values, the number  4  on the left and 10  on the right. A common example of using abstract syntax trees is in compilers. A compiler accepts source code as input, and then outputs another language. This is often from a high-level programming language to something low-level, like machine code. A common example in frontend development is transpilation, where modern JavaScript is transpiled to an older version of JavaScript syntax. But how does this impact you as a frontend engineer? First, you likely rely on tooling built on top of abstract syntax trees on a daily basis. Some common examples of frontend build tools or compilers that rely on abstract syntax trees are webpack ,  babel , and swc. However, they aren't isolated to build tools. Tools like Prettier (code formatter) , ESLint (code linter) , or jscodeshift (code transformer) have different purposes but they all rely on abstract syntax trees since they all need to understand and work with source code directly. It's possible to use most of these tools without an understanding of abstract syntax trees, but some have an expectation that you understand ASTs for the more advanced uses. For example, to create a custom linting rule with ESLint, or a custom code transform with jscodeshift requires traversing and mutating ASTs. Trying to use these tools without this understanding can be a challenging and confusing experience. One of the biggest benefits is using tools like babel or swc directly to generate, traverse, and mutate ASTs. This enables interacting with code in a reliable and automated way and many of the tools mentioned earlier use these or equivalent tools internally. This allows creating completely custom functionality to statically analyze/audit code, make dynamic code transformations, or whatever problem you might be solving in a large codebase. While it's not necessary to understand abstract syntax trees to be a productive and successful frontend engineer, having a basic understanding can uplevel your ability to maintain continuously evolving large codebases and more easily interact with common tools that rely on them.  Abstract syntax trees enable interacting with a codebase "at scale." For more on how to make sweeping changes in a safe and reliable way in any size codebase, check out our course  The newline Guide to Practical Abstract Syntax Trees.

Thumbnail Image of Tutorial Why should I care about abstract syntax trees as a frontend engineer?

The newline Guide to Practical Abstract Syntax Trees is Now Live! 🎉

Learn the practical techniques you need today to modify any large-scale codebase without the hassle of manual, one line at a time refactors.  We use real world tools such as Facebook's jscodeshift to apply these powerful concepts on actual codebases. The course goes beyond just theory to practical hands on coding , with a sample codebase we provide that you will modify as you apply the techniques you learn in the course. With  Practical Abstract Syntax Trees  you  unlock the ability to make sweeping changes in a safe and reliable way in any size codebase . We'll tackle:  It's taught by Spencer Miskoviak, who's an engineer at WealthFront, the leading automated investing services firm with over $20 billion in assets under management (AUM). Spencer is a recognized expert on ASTs and JavaScript. He presented on ASTs at React Conf in 2019, showing advanced ways to optimize a JavaScript codebase. Access The newline Guide to Practical Abstract Syntax Trees for all of the practical techniques you need to maintain any size codebase.

Thumbnail Image of Tutorial The newline Guide to Practical Abstract Syntax Trees is Now Live! 🎉

NPM: What are project dependencies?

Code dependencies are like Lego's . We're able to pull in other people's code; combining and stacking different packages together to fulfill our goals. Using dependencies greatly reduces the complexity of developing software. We can take advantage of the hard work someone has already done to solve a problem so we can continue to build the projects we want. A development pipeline can have multiple kinds of code dependencies: In JavaScript, we have a package.json file that holds metadata about our project. package.json can store things like our project name, the version of our project, and any dependencies our project has. Dependencies, devDependencies, and peerDependencies are properties that can be included in a package.json file. Depending on the instance where code will be used changes the type of dependency a package is. There are packages that our users will need to run our code. A user is someone not directly working in our code-base. This could mean a person interacting with an application we wrote, or a developer writing a completely separate library. In other words, this is a production environment. Alternatively, there are packages that a developer or system only needs while working in our code. For example linters, testing frameworks, build tools, etc. Packages that a user won't need, but a developer or build system will need. Dependencies are packages our project uses in production . These get included with our code and are vital for making our application run. Whenever we install a dependency the package and any of its dependencies get downloaded onto our local hard drive. The more dependencies we add, the bigger our production code becomes. This is because each new dependency gets included in the production build of our code. Evaluate adding new dependencies unless they're needed! Dependencies are installed using npm install X or yarn add X Packages needed in development , or while developing our code, are considered dev dependencies. These are programs, libraries, and tools that assist in our development workflow. Dev dependencies also get downloaded to your local hard drive when installed, but the user will never see these dependencies. So adding a lot of dev dependencies only affects the initial yarn or npm install completion time. Dev Dependencies are installed using npm install --save-dev X or yarn add --dev X Peer dependencies are similar to dependencies except for a few key features. First, when installing a peer dependency it doesn't get added to your node_modules/ directory on your local hard drive. Why is that? Well, peer dependencies are dependencies that are needed in production , but we expect the user of our code to provide the package. The package doesn't get included in our code. This is to reduce including multiples of the same dependency in production . If every React library included a version of React as a dependency, then in production our users would download React multiple times. Peer dependencies are a tool for library owners to optimize their project size. Peer Dependencies are installed using yarn add --peer X I recently released a course, Creating React Libraries from Scratch, where we walk through content just like how NPM dependencies work, and a lot more! We start with an empty project and end the course with a fully managed library on npm. To learn more click the link below! Click to view Creating React Libraries from Scratch!

Thumbnail Image of Tutorial NPM: What are project dependencies?

A Closer Look at ReactDOM.render - The Need to Know and More

📰 In this post, we will learn about render(), a core function of ReactDOM. Along with this, we will also take a closer look at the reconciliation process, how ReactDOM works under the hood, and it's use-cases.The ReactDOM library is not often talked about when working with React, however, It is vital for any React developer to know how ReactDOM.render is used to inject our React code into the DOM. It is also good to get a brief idea of how it works under the hood, so we can write better code to accommodate the architecture. According to the React docs , This blog post presents an overview of the ReactDOM library. Since it involves some core ReactJS concepts, it is better to be familiar with the library and how it works. Even if you don't have a deep understanding of React, this blog post can help demystify a lot of concepts related to rendering on the DOM. Before moving to ReactDOM, let's take a brief look at the Document Object Model. The Document Object Model (DOM) is a code representation of all the webpages that you see on the internet. Every element , such as a button or image that you see on the web-page is a part of a hierarchy of various elements within a tree structure. This means each element (except the root element) is a child of another element. This structure enables you to easily interface your JavaScript code with HTML to create highly powerful and dynamic web applications. The way that web developers usually work with the DOM to develop interactive websites, is by finding a DOM node and making the required changes to it, such as changing an attribute or adding a child node. However, for highly dynamic web applications where the DOM needs to be updated frequently, applying these required changes can be a slow process, as the browser ultimately has to update the entire DOM every time. To combat this problem, React works with a Virtual DOM , which is just a representation of the actual DOM that is used behind the scenes to optimize the update process. When a React element is updated, ReactDOM firstly updates the Virtual DOM. After that, the difference between the actual DOM and the Virtual DOM is calculated, and only the unique part . This means that the whole DOM does not need to be updated every single time. This process, also known as “reconciliation” , is one of the things that helps us to build blazing fast Single Pages Applications (SPAs) with React. ReactDOM is a package that provides methods that can be used to interact with the DOM, which is needed to insert or update React elements. It provides many helper functions such as: And more... Most of the time when building Single Page Applications (such as with create-react-app ), we usually create a single DOM container and call the render method once to initialize our React application. Since this method is always used when working with React, learning about the working of ReactDOM.render can greatly benefit us as React developers. The render method can be called the primary gateway between React and the DOM. Let’s say you have defined a React element ( <Calculator /> ), as well as a DOM node to act as a container for that element (div with the ID of “container”). Now, you can use ReactDOM.render to render the element within that container using the syntax given below: ReactDOM.render(< Calculator />, document.querySelector("#container")) The statement above returns a reference to the component that you have created. If it is a functional component, it returns null. Parameters: React elements are defined in a tree structure . This means each element is essentially a child of another React element. However, for the root element, we need to create an element (DOM Node) in our HTML code to act as a container for our React element tree, which can be accessed via ReactDOM.rende r. For a better understanding, the figure below defines an example React component tree: In the above diagram, we can see that <Calculator /> is our root React element , which is rendered into the container div within the HTML code. Breaking it down further, the <Calculator /> element has two children, <Display /> and <KeyPad / >. Similarly, <KeyPad /> is broken down into <NumKeys /> , <FunctionalKeys /> and <Operators /> . This is what those components will look like in code: As defined above, the reconciliation process is when the React virtual DOM (AKA the tree of React elements) is checked against the actual DOM, and only the necessary updates are reflected. In the previous versions of React, a linear synchronous approach was used to update the DOM. It became obvious very quickly that this can greatly slow down our UI updates, negating the whole reason why reconciliation exists in the first place. In React 16, the team re-wrote major parts of the reconciliation algorithm to make it possible to update the DOM asynchronously. This is possible because of the Fiber architecture which lies at the core of the new implementation. Fiber works in two phases, This phase is triggered when a component is updated through state or props. Therefore, the standard React protocol is followed, where a component is updated and lifecycle hooks are called, after which the DOM nodes that need to be updated are calculated. In Fiber, these activities are termed as “work” . Before React 16, having multiple work tasks could make our user interface look and feel sluggish because a recursive approach was used with the call stack. The problem with recursion is, that the process only stops when the call stack is empty, which can result in higher time complexity. As more work is performed, more computational resources are utilized. The updated architecture utilizes the Linked List Data Structure within its algorithm to handle updates. This, used in conjunction with the requestIdleCallback() function provided by newer browsers makes it possible to perform asynchronous tasks (or work) more efficiently. Each “work” unit is represented by a Fiber Node . The algorithm starts from the top of the Fiber Node Tree and skips nodes until it reaches the one which was updated. Then it performs the required work and moves up the tree until all the required work is performed. During the commit phase, the algorithm first calls the required lifecycle methods before updating or unmounting a component. Then, it performs the actual work, that is, inserting, updating or deleting a node in the DOM. Finally, it calls the post-mutation lifecycle methods componentDidMount and componentDidUpdate . Along with this, React also activates the Fiber Node Tree that was generated in the previous phase. Doing this ensures synchronization between the tree of React elements and the DOM, as React knows what the current status of the Virtual DOM is. Whew... however abstract, we now have a faint idea of how the reconciliation process works behind the scenes. Let’s move back to the practical side of things, and discuss how we can use ReactDOM.render in different scenarios. Assuming we are working with a Single Page Application, we will only need to instantiate the root element (usually App.jsx ) at a single location in the DOM. Therefore, oftentimes the lone index.html file is not even touched at all. All we need to do is create a container, and render our React root element to it, as described above in the Calculator example. We can also use ReactDOM.render to integrate React in a different application. This is why we call React a library, not a framework . You can use it as little as possible or as much as possible, as it completely depends on your use-case. We can create a wrapper function for our React module. All the required props can be passed to the function, and sent down to the component which is rendered through ReactDOM.render, just like it would be for a single page application. It is important to export the function, as we will need to call it within our JavaScript code. In the index.html file shown above, we are importing the script that renders our root React component, and then we call the function using plain JavaScript. We can also pass parameters, such as props for our React component, through this function. It is better to initialize React components after the document has loaded. You can also use ReactDOM.render multiple times throughout the application. This means that if you are creating a new website, or modifying an existing website that does not use React yet, you can use ReactDOM.render to generate some pages using React, while others do not use the library. When you unmount a React component from the DOM, it is important to call unmountComponentAtNode() according to the syntax given below to ensure there are no memory leaks. ReactDOM.unmountComponentAtNode( DOMContainer ) This is why the React team suggests using a wrapper for your React root elements. Doing this ensures that you can mount and unmount React nodes according to the design of your website. For example, moving from one React page to another that uses separate React root elements, it is possible to integrate the wrapper API with the page transition, which can automatically unmount the component for you. Similarly, you can also write the logic in your wrapper to unmount a React root component within the same page, as soon as its work is done. To update a component, you may call ReactDOM.render again for the same React element and DOM node. However, one thing that is important to note is that ReactDOM.render completely replaces all of your props each time this function is called. This means, you must also pass all of the other required props to the element that you are rendering, which can be an issue. The reason for the props being replaced is because React elements are immutable. The React team explains how you can create a wrapper to set the previous props again . Although render() is the most commonly used ReactDOM method, there are a few more available at your disposal. Let’s take a look at two of those. It is similar to render() , however, it is used when rendering pages through Server Side Rendering (SSR) . It integrates the necessary event handlers and functions to the markup that has been generated. Portals can be created to render a component outside of the React component tree of that specific component. This can be highly useful to generate elements somewhere unrelated on the page. To sum it up, ReactDOM acts as a powerful interface between our React component tree and the DOM. The most commonly used method from ReactDOM is render() , which can be used to connect entire React applications to the DOM. Once the React element and it’s child tree have been inserted into the DOM, the reconciliation process handles everything related to updates. Due to this process, whenever we update a part of our component tree, only the changes in that part are reflected in the actual DOM, thereby saving us a lot of extra computation. React and ReactDOM provides powerful functions such as render() that make it easy to create fast and snappy Single Page Applications through React, which makes React such a popular front-end development library.

Thumbnail Image of Tutorial A Closer Look at ReactDOM.render - The Need to Know and More