How to Increase Performance for the React App (Part-2)
Introduction
In this article, we’ll show you how you can increase the stunning performance of React app. We already discussed this in my previous blog Methods of How to Improving and Optimizing Performance in React Application Part-1. In this article, we are going to discuss it with some other new topics. This blog will look at how you can use things like react-santa to help you get better performance in your app.
Let’s have a Look!
React Fragment
React Fragments are a new approach to adding numerous elements to a React Component without having to wrap them in extra DOM nodes. We utilize the render method to render a component, which renders a single root node at a time. We must contain numerous elements in a wrapper element whenever we need to render them. Without a wrapper element, the component will not be rendered on the DOM.
Whenever we need to render multiple components on a single page, we wrap those components into a ‘div’ tag. But instead of using the ‘div’ tag we should use React.Fragment as Fragment does not create its corresponding JSX. By using Fragment, DOM does not create extra elements so DOM size reduces and makes the app a tiny bit faster.
import React from 'react' const ReactFragment = () => { return ( <> <div>ReactFragment</div> <p>Wraped 2 components in a Fragment</p> </> ) } export default ReactFragment OR import React, { Fragment } from 'react' const ReactFragment = () => { return ( <Fragment> <div>ReactFragment</div> <p>Wraped 2 components in a Fragment</p> </Fragment> ) } export default ReactFragment
You can use fragments in 2 ways:
Simply wrap components with React.Fragment
Wrap components with <></>
Both ways are valid and will not create extra tags in DOM. You can understand more with the above example.
If we use div instead of Fragment then div will reflect on DOM. And both ways will give the same result. In the above image, There is no extra tag as we use Fragment in this. But in the image below, there is an extra div tag as we wrap components with div.
Lazy Loading
By using Code-splitting methods, we can make React apps faster. React.lazy and React.Suspense is used for code-splitting in react. This feature was introduced to React v16.
React.lazy takes a function that must call a dynamic import(). This must return a Promise which resolves to a module with a default export containing a React component.
The lazy component should then be rendered inside a Suspense component, which allows us to show some fallback content (such as a loading indicator) while we’re waiting for the lazy component to load.
import React, { Suspense } from 'react'; const ReactWithoutFragment = React.lazy(() => import('../UseOfFragment')); function MyComponent() { return ( <div> <Suspense fallback={<div>Loading...</div>}> <ReactWithoutFragment /> </Suspense> </div> ); }
The fallback prop accepts any React elements that you want to render while waiting for the component to load. You can place the Suspense component anywhere above the lazy component. You can even wrap multiple lazy components with a single Suspense component.
In the above example, the ReactWithoutFragment component is imported by React lazy and Wrapped with Suspense, so until the component renders fallback render first it enhances the user experience. You can also use Suspense and lazy loading in the react-router.
Error Boundary
You can easily run into a situation where the component rendering results in an error.
In such cases, the component error should not break the entire application. Creating error boundaries ensures that the application does not break in case of an error in the specific component.
Error boundaries are a React component that catches JavaScript errors anywhere in the child component. We can contain the error, log the error messages, and have a fallback mechanism for the UI component failure.
Error boundaries are based on the concept of higher-order components.
Error boundaries involve a higher-order component, containing these methods: static getDerivedStateFromError() and componentDidCatch().
The static function is used to specify the fallback mechanism and derive the new state for the component from the error received.
The componentDidCatch function is used to log error information to the application.
class ErrorBoundary extends Component { state = { error: null, }; static getDerivedStateFromError(error) { return { error }; } render() { const { error } = this.state; if (error) { return ( <div> <p>Something went wrong!!</p> <p>{error.message}</p> </div> ); } return this.props.children; } } export default ErrorBoundary;
The above code is for the Common Component of the Higher-order component to handle errors.
import React from 'react'; function ErrorCode() { const [name, setName] = React.useState() const handleError = () => { setName(() => { throw new Error("Opps! Something went wrong"); return "Erron set" }) } return ( <> <h2>{name}</h2> <button onClick={handleError}>error generate</button> </> ) } export default ErrorCode;
In the above code, we generate the error with the click of a button and assign some error messages. And wrap the above component to the ErrorBoundry component.
<ErrorBoundary> <ErrorCode /> </ErrorBoundary>
When pressing the button, the ErrorBoundry component renders and give the below result:
ErrorBoundry helps to enhance the user experience without breaking the Application.
React Clean Code (Advantage of Object Literals)
Object literals can help make our code more readable. Let’s say you want to show three types of users based on their roles. You can’t use ternary because the number of options is greater than two.
import React from 'react' import AdminUser from './AdminUser' import StudentUser from './StudentUser' import NormalUser from './NormalUser' function RoleBaseComponent({ user }) { const { role } = user switch (role) { case ADMIN: return <AdminUser /> case STUDENT: return <StudentUser /> case USER: return <NormalUser /> } } export default RoleBaseComponent
In the above example, it will take some time as it’s going to check for the condition based on role. And it is time-consuming and increases the line of code which is not expected. In the below code, By advantage of Object Literals, code can be optimized.
import React from 'react' import AdminUser from './AdminUser' import StudentUser from './StudentUser' import NormalUser from './NormalUser' function RoleBaseComponent({ user }) { const { role } = user const components = { ADMIN: AdminUser, EMPLOYEE: StudentUser, STUDENT: NormalUser }; const Component = components[role]; return <Component />; } export default RoleBaseComponent
React SEO friendly
SEO (search engine optimization) is a big and complex area. To summarize SEO is about making it easier for Google to find the right content for the user. When a user makes a search Google tries to find which page is the most relevant to that specific search.
We can use React Helmet for performance optimization for react applications. React Helmet gives access to the HTML head tag. We can use meta, title, description, NoScript, etc in the
Helmet.
import React from "react"; import { Helmet } from "react-helmet"; export default function ReactHelmet() { return ( <div className="App"> <Helmet> <title>React Helmet</title> <meta name="description" content="Helmet app" /> </Helmet> <p>React helmet demo</p> </div> ); }
We can wrap HTML head tag components and tags in Helmet. It helps to increase SEO performance. You can find the result in the below image:
We also can achieve SEO-friendly applications by using server-side rendering. We can use frameworks to achieve Server side rendering in React apps. Like
1. Next.js https://nextjs.org/
2. Gatsby.Js https://www.gatsbyjs.com/
Reference:
https://reactjs.org/docs/error-boundaries.html
https://medium.com/@sathamasatham/clean-code-react-project-9e0ee727cc27