Our Global Presence

Canada
57 Sherway St,
Stoney Creek, ON
L8J 0J3

India
606, Suvas Scala,
S P Ring Road, Nikol,
Ahmedabad 380049

USA
1131 Baycrest Drive,
Wesley Chapel,
FL 33544
Frontend development is very important these days. There are a lot of tasks that a frontend developer has to do on a daily basis.
As front-end developers, we write a lot of HTML, CSS, and JavaScript code all the time. Knowing some coding tips could be very beneficial for us. That’s why in this article, I decided to share with you some frontend coding tips that you probably don’t know.
Do you know that you can hide an HTML element without using JavaScript?
By using the attribute hidden, you can easily hide an HTML element natively. As a result, that element won’t be displayed on the web page.
Here is the code example:
<p hidden>This paragraph won't show up. It's hidden by HTML.</p>
It’s always a good practice to use shorthands in order to make your CSS code smaller. The property inset in CSS is a useful shorthand for the four properties top , left , right , and bottom .
If these four properties have the same value, you can just use the property inset instead and your code will look much cleaner.
Here is an example:
Bad practice:
div{ position: absolute; top: 0; left: 0; bottom: 0; right: 0; }
Good practice:
div{ position: absolute; inset: 0; }
You can easily detect internet speed in JavaScript by using the navigator object. It’s very simple.
Here is an example:
navigator.connection.downlink;
Pic courtesy: blog.devgenius.io
As you can see above, it gives me 5.65 since my internet speed is not good at all.
Again, you can easily use the method vibrate()in the navigator object to vibrate your phone.
Here is an example:
//vibrating the device for 500 milliseconds window.navigator.vibrate(500);
So as you can see, the device in this situation will vibrate for 500 milliseconds.
By using only CSS, you can disable pull to refresh on mobile. The property overscroll-behavior-y allows us to do that. Just give it the value contain .
Here is the example:
body{ overscroll-behavior-y: contain; }
There will be situations where you will need to prevent the user from pasting text into inputs.
Well, you can easily do that in JavaScript using a paste event listener.
Here is an example:
<input type="text"></input> <script> //selecting the input. const input = document.querySelector('input'); //prevent the user to paste text by using the paste eventListener. input.addEventListener("paste", function(e){ e.preventDefault() }) </script>
As a result, now users can’t paste the copied text into the input field.
Databases are the backbone of our applications, and the more you learn about how they work, the better you will be at using them, writing applications against them, and troubleshooting problems when things inevitably go wrong.
So let’s dive into seven things you should (probably) know about databases.
We’ve seen a lot of dogmatic fist-banging about “the best” or “the worst” database, but the truth is the best database is the one that works best for your application. There’s no one-size-fits-all sort of database just like there’s no one-size-fits-all programming language or operating system.
When starting a new project, choosing the right database can be one of the most crucial decisions that you’ll make. So how should you choose which DB to use? We put together a list of five things to consider in our article on databases for developers, but let us also quickly go through them here.
What kind of data will be stored in the database?
Are you storing log files or user accounts?
How complex is the data that will be stored?
Can the data be normalized easily?
How uniform is the data?
Does your data roughly follow the same schema or is it disparate or heavily nested?
How often will it need to be read or written?
Is your application read- or write-heavy, or both?
Are there environmental or business considerations?
Do we have existing agreements with vendors? Do I need vendor support?
By answering these questions, you can help narrow down your choices to a few candidates. Once there, testing should tell you which one is the best for your application.
Sometimes you don’t have a choice and the database is already chosen for you. Whether you came to the project after it was started or political winds forced you a certain way, using the wrong database for the job can be frustrating.
But equally, if not more, frustrating is the progress of migrating databases should you get the opportunity. Once you start down one path, it’s not easy to simply change paths in the middle of things. Not only do you have to figure out a way to replicate your data from one database to another and learn a whole new system, but depending on how tightly coupled your database code is with the rest of your application, you might also be looking at extensive rewrites as well. Changing databases is not a task that should be undertaken lightly and without a lot of consideration, debate, testing, and planning. There are so many ways that things can go horribly wrong. This is why #2 is so important: Once you choose, it’s hard to undo that choice.
The debate about using a SQL or NoSQL database will go on forever. We get that. But often missed in this argument is the fact that NoSQL databases don’t replace SQL databases. They complement them.
There are some things that NoSQL databases do very well and there are some things that SQL databases do very well. Prometheus is very good at storing time-series data like metrics, but you wouldn’t want to use MySQL for that. Is it technically possible? Yes, but it’s not designed for that and you’re not going to get the best performance or developer experience out of it. On the flip side, you wouldn’t want to use Redis to store highly relational data like user accounts or financial transactions for the same reasons. Sure, you could make it work in the code, but why add that complexity and headache when you could just use the right tool for the job?
There is going to be some inevitable overlap in some areas. There are some excellent databases that are technically NoSQL that do a good job of storing relational data (see: Couchbase), but there are other outside factors that go into using one over the other. Factors like client language support, operational tooling, cloud support, and others are all things to take into account when choosing a database.
For more information and to develop web applications using modern front-end technology, Hire Front-End Developer from us as we give you a high-quality solution by utilizing all the latest tools and advanced technology. E-mail us any clock at – hello@hkinfosoft.com or Skype us: “hkinfosoft“.
To develop your custom web app using JavaScript, please visit our technology page.
Content Source:
React 17 was focused on improving the fundamentals but there are few important things that got added in React 18. The React Team revealed new features that would be coming to React in React 18 and in this blog, we will explore these features and how they can help you in the near future!
Strict Mode has a few additions such as a new behaviour called “strict effects”. This allows us to double-invoke effects like mount and unmount. It creates an environment to correct behaviour with Fast Refresh during development, not only looking for more resilient components. There is also an ‘offscreen API’ which is currently being built.
An offscreen API will enable better performance by hiding components instead of unmounting them, keeping the state, and still calling the mount/unmount effects.
There is now major improvements with automatic batching. We will first look at performance.
React already batched, in other words grouped, multiple state updates into one to minimise unnecessary re-renders. However, elements like Promises, timeouts, or other handlers didn’t take advantage of it as it was only limited to DOM event handlers.
This all changes with React 18 which will batch state updates without limits, as long as it’s safe to do. The result, you ask?…This would create better performance without any additional involvement.
There are huge improvements to automatic batching. In the earlier versions of React, it uses to batch multiple state updates into one to reduce unnecessary re-renders. The problem was it was done only in DOM event handlers and not in promises, timeouts, or other handlers.
Let’s look at the below code on how batching occurs with earlier versions of React.
export default function App() { const [count, setCount] = useState(0); const [color, setColor] = useState(undefined); const handleClick = () => { setCount(count + 1); //No re-render setColor(count % 2 === 0 ? "Green" : "Red"); //No re-render // Now re-renders once at the end (this is batching) } return ( <> <button onClick={handleClick}>Next</button> <span style={{ color: count % 2 === 0 ? "red" : "green", }}> {color} </span> </> ); }
With React 18, promises, timeouts, or other handlers will also take advantage of that. It will batch state updates no matter where they happen. This will result in better performance.
Let’s look at the below code where batching occurs. In the below code batching works fine with React 18 but earlier versions of React will not batch it.
export default function App() { const [count, setCount] = useState(0); const [color, setColor] = useState(undefined); const handleClick = () => { Promise.resolve().then(() => { setCount(count + 1); //Re-render setColor(count % 2 === 0 ? "Green" : "Red"); //Re-render }); } return ( <> <button onClick={handleClick}>Next</button> <span style={{ color: count % 2 === 0 ? "red" : "green", }}> {color} </span> </> ); }
However, if there is a need where we don’t want our component to be batched, we can opt-out that component using ReactDOM.flushSync().
Concurrent rendering is definitely one to look for as it is by far the biggest update with React 18.
Prior to this name, it was called ‘concurrent mode’. The change in name signifies the enabling of gradual adoption of concurrent features. This allows us to adopt concurrent features without rewriting code and do so at your own pace.
With React 18, we get several new APIs which come in many forms.
Its purpose is to spot state updates as transitions, making handling them non-urgent.
This hook will give you a deferred element of the passed value, which will follow the original one, up to provided timeout.
The ‘useDeferredValue’ is a hook that will return a deferred version of the passed value. It takes in the state value and a timeout in milliseconds. It will return a deferred version of the value that may “lag behind” it for most timeouts.
import { useDeferredValue } from "react"; const [text, setText] = useState("react js"); const deferredText = useDeferredValue(text, { timeoutMs: 2000 });
This is commonly used to keep the UI responsive when we have something that renders immediately based on user input and something that needs to wait for a data fetch.
In the previous version of react, the below code would result in ReadyComponent being immediately mounted and its effects called. Like its name, Suspense suspends something until it’s ready to be rendered.
<Suspense fallback={<Loading />}> <ComponentWaitingForData /> <ReadyComponent /> </Suspense>
This has been taken care of in React 18.
Referring to the above code, Now it won’t mount the ReadyComponent, instead will waiting for ComponentWaitingForData to resolve first.
A SuspenseList excepts a two prop. ‘revealOrder’ and ‘tail’.
‘revealOrder’ is one of SuspenseList configuration options. It can be undefined, together, forwards, and backwards.
‘tail’ props dictates how the unloaded items in a SuspenseList are shown. Its value can either be collapsed or hidden.
<SuspenseList revealOrder="forwards" > <Suspense fallback={<p>Loading attendance...</p>}> <Attendance id={facultyID}/> </Suspense> <Suspense fallback={<p>Loading homework...</p>}> <Homework id={facultyID}/> </Suspense> </SuspenseList>
The above code with SuspenseList demonstrates that we can set the revealOrder to force the attendance to appear first and then the homework section.
<SuspenseList revealOrder="forwards" tail="collapsed"> <Suspense fallback={<p>Loading attendance...</p>}> <Attendance id={facultyID}/> </Suspense> <Suspense fallback={<p>Loading homework...</p>}> <Homework id={facultyID}/> </Suspense> </SuspenseList>
The above code demonstrates that only one fallback is shown at a time. i.e first the fallback for the attendance and then the fallback for the homework.
createRoot will replace the render function. The new API is the gateway to accessing new React 18 features. It’s meant to encourage gradual adoption and ease-out potential performance comparisons.
For more information and to develop web application using React JS, Hire React Developer from us as we give you a high-quality product by utilizing all the latest tools and advanced technology. E-mail us any clock at – hello@hkinfosoft.com or Skype us: “hkinfosoft”. To develop custom web apps using React JS, please visit our technology page.
Content Source:
Angular provides unmatchable features that make it the most preferred framework in the Web Development industry today. The Angular version 12.0.0 release has come up again with the most compelling features and customization options to take your development journey to a new horizon. The new release of the Angular 12.0.0 version brings updates on the framework, the CLI, and components.
Let’s have a look at the unique and unparalleled features in Angular 12.0.0:
The Angular team has focused on enforcing secure and strict methods of checking for reactive forms. The new update will help developers to look out for issues in the development stage. This upgrade will also enable better text editor and ide support allowing the developer better developer ergonomics with strict typing for Angular/forms. The previous versions were not as aggressive in addressing this issue, but Angular 12 does it perfectly.
When the transition to Ivy of all internal tooling gets done, removing the legacy View engine becomes the next challenge. No worries! The newly added removing legacy View Engine aims to reduce framework overheads. This is because of smaller Angular conceptual overhead, smaller package size, saving on maintenance cost, and decrease in the complexity of the codebase. With the knowledge of Ivy, it’s the best path to take while using the latest version of Angular. An application that has upgraded to the latest version of Angular (Angular 12.0) and is keeping enable Ivy as false, should consider this since in the future they cannot upgrade to the latest version if they don’t start using Ivy.
Design and implement a plan to make Zone.js optional. This will, in turn, simplify the framework, improve debugging, and minimize application bundle size.Zone.js does not support native async/await syntax and when Zone.js is optional and a developer can choose not to use it then Angular will be able to support native async/ await syntax.
Testbed automatic clean-up and tear down of the test environment after each test run, will improve test time and create better isolation across tests.
This will simplify the Angular mental model and learning. This will allow the developers to develop standalone components and implement other types of APIs for the declaration of the component compilation scope. On the other hand, we have to note that this change might make it hard for existing applications to migrate to this.
This feature will allow developers to have more control over the compilation scope for a particular component without giving much thought to the NgModule they belong to.
Adding directives to host elements has been on high request by Angular developers for a long time. The new release allows developers to architecture their components with additional characteristics without using inheritance. At the moment you cannot add directives to host elements, but you can improvise using: host CSS selector. As the selector of these components also becomes a DOM element, we could have more possibilities if we could add more directives to this element too.
The Angular compiler being distributed as a TypeScript plugin will significantly improve the developer’s build performance and reduce the cost.
The slow initial load time is the major problem with web applications. Applying more granular code-splitting on a component level can solve this problem. This will mean smaller builds and faster launch time and in return result in improved FCP.
That’s all for the new release.
Now, let us take a look at the possibilities that are in progress and will be available shortly.
Firstly, this will result in faster applications. Loading external stylesheets is a blocking operation. This means that the browser cannot initiate rendering an application without first loading all the referenced CSS. Its FCP (First Contentful Paint) can be improved by having a render-blocking in the header of a page that can visibly improve the load performance.
To date, the Angular language service still uses the View Engine compiler and type checking even for Ivy applications. The goal is to improve the experience and to remove the legacy dependency. This will be achieved by transitioning from View Engine to Ivy. The team at Angular wants to start using the Ivy template parser and improved type checking for the Angular language service to match Angular application behaviour. This will simplify Angular, npm size reduction, and improve the framework’s maintainability.
The error messages bring limited information on how a developer can take actions to resolve them. The Angular team is working on codes, developing guides, and other measures to ensure an easy debugging experience and make error messages more discoverable.
In conjunction with the Google security team, the Angular team is working on adding support for the new Trusted Type API. This API will aid developers to make more secure web applications.
With Angular, the CLI Webpack 5 stability will continue urging for the implementation to enable build speed and bundle size improvements.
Integrating MDC weblink will align Angular Material closely with the material design specification, expand the accessibility reach, improve component quality and improve the overall team velocity.
The team at Angular could focus its attention on working on tooling that will help in the provision of utilities for debugging and performance profiling. The primary aim is to help the developers understand the component structure and the means to note changes in the angular application.
MDC web is a library created by the Google Material Design team that provides reusable primitives for building material design components.
For more information and to develop web applications using Angular, Hire Angular Developer from us as we give you a high-quality product by utilizing all the latest tools and advanced technology. E-mail us any clock at – hello@hkinfosoft.com or Skype us: “hkinfosoft”.
To develop your custom web app using Angular, please visit our technology page.
Content Source:
Web developers love nothing more than finding amazing extensions that accelerate the development process.
One such tool is Chrome DevTools, which offers a lot of features and it is the go-to tool for frontend developers, of all levels.
DevTools has a wide array of features and options, and Google has done a fantastic job documenting this tool.
However, despite the comprehensive documentation, there is still a list of helpful tools and features that most developers don’t know about.
From emulating mobile devices to finding useless JavaScript code, we’ll be covering 9 secret features the DevTools has to offer in this blog.
Your website will be accessed by people from around the globe using devices of different sizes and platforms.
You can build websites that are responsive using media queries, but what about network speed?
Not every one of your visitors will have the same network speed, hence you need to check how your site behaves with different network speeds.
Luckily, DevTools has the option to switch between 3 network presets:
Pic courtesy: javascript.plainenglish.io
You also get the ability to add a custom profile.
You can find this feature under the Network tab, by clicking on the “No throttling” dropdown menu.
Pic courtesy: javascript.plainenglish.io
DevTools has an excellent code editor inbuilt.
If you’re someone who edits CSS or any code using this tool, you will absolutely love the multi-cursor support.
It’s very easy to set up as well. All you need to do is press and hold Ctrl( Command on Mac) and click on lines where you want multiple cursors.
You can also undo your selections by pressing and holding Ctrl(Command on Mac) + U.
Moreover, you can also press Alt and drag to get multiple cursors. You can see the implementation here.
For me, dark mode increases visibility & reduces eye strain. There are many upsides to using dark mode, as well as downsides.
Various articles cover this topic.
Pic courtesy: javascript.plainenglish.io
We use the dark mode wherever possible, from the Twitter app to our calculator app.
DevTools is no exception.
To enable the dark mode, open the Settings by clicking the three vertical dots present in the right corner of the screen.
Then go to Preferences > Appearance > Theme and finally select Dark.
Pic courtesy: javascript.plainenglish.io
You can quickly open a Command Menu by pressing Ctrl(CMD on Mac)+Shift+P when DevTools is opened.
It provides a fast way to navigate the DevTools and over time, you become familiar with it.
This feature is handy if you are familiar with VS Code’s Command Palette.
You can delete the > and replace it with ? to see all the features offered by this menu.
Pic courtesy: javascript.plainenglish.io
Modern JavaScript apps are becoming increasingly complicated and rely on a ton of third-party libraries.
There’s always some code that’s not used and is rendered redundant.
DevTools helps you locate such redundant code that may unnecessarily be hampering your site speed.
To do so, click the three vertical dots on the top-right corner of DevTools. Then click More Tools and select Coverage.
All you need to now is reload the page and the newly popped up panel will display the unused JavaScript code.
You can see the total bytes as well as the unused bytes along with the visual usage bar.
If your primary browser is some other browser that doesn’t offer such tools, and you only use Chrome for the Devtools, then this feature can be incredibly useful to you.
Pic courtesy: javascript.plainenglish.io
There is a global option under DevTools settings to auto-open DevTools for popups.
However, the better way of doing this is by starting DevTools not just on popups but with the Chrome browser itself.
You can do so by adding the following line as a property on Google Chrome.
"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --auto-open-devtools-for-tabs
And for Mac users,
--auto-open-devtools-for-tabs
You can refer to the answers here to learn more options to enable DevTools.
Pic courtesy: javascript.plainenglish.io
Color Picker is a great way to select the exact color you need and be able to easily add it to the CSS of your site.
DevTools offers a color picker and accessing it is a very straightforward process.
Go to the Elements tab and from there select the Styles panel to see the CSS.
Simply click on the color square (not the value) and the color picker will show up.
The color picker has the ability to easily convert between color modes, like from HEX to RGBA.
Pic courtesy: javascript.plainenglish.io
Over 60% of all online searches are performed by mobile devices, making responsive web design a critical part of web development.
Fortunately, DevTools offers a mobile emulator, which has predefined height and width which match that of some popular mobile devices like iPhone, Pixel, Surface, and iPad.
Open DevTools and click the Toggle Device Toolbar as shown in the media above.
You can also choose between mid-tier or low-tier mobile from the “No Throttling” drop-down menu.
Additionally, dragging the handles to resize the viewport is another handy option to get the exact dimensions you need.
Pic courtesy: javascript.plainenglish.io
Ever wondered how many media queries sites like YouTube have? You can easily check it by enabling the option to see media queries.
Just click the 3 vertical dots as shown in the media above and enable media queries visibility.
You will see a new panel showing various media query breakpoints which you can click to apply.
Besides this, you can also set breakpoints in your JavaScript code quite easily.
One way to do this is by writing debugger in your code, which will pause the execution when debugger is reached.
console.log('a'); console.log('b'); debugger; console.log('c');
The other way is to go to the Sources tab and then head over to the code file and find the line where you want to pause the execution.
Then you have to click the line number on the left side of your code, which will make a blue icon appear on that line number. That’s it.
DevTools will pause before this line of code is executed.
For more information and to develop web applications using modern front-end technology, Hire Front-End Developer from us as we give you a high-quality solution by utilizing all the latest tools and advanced technology. E-mail us any clock at – hello@hkinfosoft.com or Skype us: “hkinfosoft“.
To develop your custom web app using JavaScript, please visit our technology page.
Content Source:
Dependency Injection (DI), sometimes referred to as ‘Inversion of Control’, is when an object receives other objects or functions it depends on for part of its functionality. This can be achieved by passing an object through object instantiation with a constructor or with a property setting. This is very common in the world of statically typed languages like Java or C#. There are many popular frameworks built specifically for managing dependencies in the statically typed object-oriented world.
DI allows specific functionality to be loaded at runtime. One of the advantages of being able to change the functionality of an object at runtime is to provide greater flexibility and make our applications more loosely coupled. A very common use case is using mocking during testing. There are some great libraries in Node.js like Sinon that make mocking very easy, but we can accomplish the same task by using DI.
It is very common with testing to substitute code that communicates with a database or a network request with a mock or fake. This is because in a lot of CI/CD workflows the build or testing server may not have access to a database server or a network needed for the actual service. This is an excellent use case for DI to substitute an actual service with a mock or fake service.
There are many different reasons to use DI, but testing is one of the most common reasons.
We have a technique that We have used throughout the years for configuring DI in my applications whether they are statically typed or duct-typed like JavaScript that We like to call ‘Poor Mans Dependency Injection’. With this technique, We usually create default dependent objects if a required object is not passed in on object instantiation.
Lets’ say we have a cart object that needs to calculate a tax rate for a certain location. In a lot of e-commerce systems that kind of data has to be calculated based on the location of the user, with the sales tax being different for every location. We can create a factory function that creates a shopping cart with an injectable function for calculating the tax.
function createCart(settings) { const { taxrepository } = settings; let items = []; function addItemToCart(item) { items.push(item); } function removeItemFromCart(removeThisItem) { items = items.filter((item, index, arr) => { return item.sku !== removeThisItem.sku }); } function getSubTotal() { return items.map(item => item.price * item.quantity) .reduce((accum, item) => accum + item, 0); } function getTotal() { return taxrepository(getSubTotal()) + getSubTotal(); } function getTaxes() { return taxrepository(getSubTotal()); } return Object.freeze({ addItemToCart, removeItemFromCart, getSubTotal, getTotal, getTaxes }); }
If we look at the following example, we are creating an object with functions for adding items to the cart and calculating the totals and subtotals. We have a function that we can pass into our settings constructor object called taxrepository
. We will use this function to calculate our taxes.
Lets’ create a test function for calculating our taxes. We will make this a pure function without any side effects.
function calculateMyTax(subtotal) { return subtotal * 0.11; }
When we instantiate this object with our factory function, we can just pass it into our settings object;
const cart = createCart({ taxrepository: calculateMyTax }); myCart.addItemToCart({ sku: 'DEF456', price: 2.00, quantity: 2 }); myCart.addItemToCart({ sku: 'HIG789', price: 6.00, quantity: 1 }); myCart.addItemToCart({ sku: 'ABC123', price: 12.00, quantity: 1 });
We can now get the subtotal and calculate the taxes.
console.log(`subtotal: ${myCart.getSubTotal()}`); // subtotal: 22 console.log(`taxes: ${myCart.getTaxes()}`); // taxes: 2.42 console.log(`total: ${myCart.getTotal()}`); // total: 24.42
All of the objects that We define, We try to create defaults for whenever an injectable behavior is not included in the constructor. That way if someone is using my object without passing in the needed objects, it will either get an error or a default function if it is missing from the constructor. We can modify the factory function to use a default if no taxrepository
is passed in the settings object.
We also might want to have our factory function fail if the developer calling our function forgets to pass the taxrepository
into the constructor.
if (!settings.hasOwnProperty('taxrepository')) { throw Error(`This function requires a 'taxrepository' to be passed into the contructor!`) }
DI frameworks are extremely popular in the statically typed object-oriented world of Java and .NET development, but there are DI frameworks you can use for JavaScript. One of the frameworks is called di4js, and will work with either Node.js or plain old JavaScript in the browser. Here is an example from the di4js readme;
var Car = function (engine, year) { this.engine = engine; this.year = year; }; Car.prototype.start = function () { this.engine.start(); }; var DieselEngine = function () { this.hp = 0; }; DieselEngine.prototype.start = function () { console.log("Diesel engine with " + this.hp + " hp has been started..."); }; di .autowired(false) .register('dieselEngine') .as(DieselEngine) .withProperties() .prop('hp').val(42); .register('car') .as(Car) .withConstructor() .param().ref('dieselEngine') .param().val(1976); var car = di.resolve('car'); car.start(); // Diesel engine with 42 hp has been started...
This example is from the di4js Github repo
For more information and to develop your web app using front-end technology, Hire Front-End Developer from us as we give you a high-quality solution by utilizing all the latest tools and advanced technology. E-mail us any clock at – hello@hkinfosoft.com or Skype us: “hkinfosoft“.
To develop your custom website using JS, please visit our technology page.
Content Source:
We love React!! We have been using the latest stuff from React in our latest project and found a lot of important and cool differences from the previous versions.
The following APIs will not only help you increase your productivity but also improve your code structure.
Any developer who is looking forward to learn React or even the ones who have been using React for a while should be able to use and enjoy the stuff in this article!!
import { BrowserRouter, Routes, Route, Link } from 'react-router-dom'; function App() { return ( <BrowserRouter> <Routes> <Route path="/" element={<Home />} /> <Route path="users/*" element={<Users />} /> </Routes> </BrowserRouter> ); } function Users() { /* All <Route path> and <Link to> values in this component will automatically be "mounted" at the /users URL prefix since the <Users> element is only ever rendered when the URL matches /users/* */ return ( <div> <nav> <Link to="me">My Profile</Link> </nav> <Routes> <Route path="/" element={<UsersIndex />} /> <Route path=":id" element={<UserProfile />} /> <Route path="me" element={<OwnUserProfile />} /> </Routes> </div> ); }
The above is standard code that is used to created routes for navigation in React projects.
Now let’s check React router v6 code:
import { BrowserRouter, Routes, Route, Link, Outlet } from 'react-router-dom'; function App() { return ( <BrowserRouter> <Routes> <Route path="/" element={<Home />} /> <Route path="users" element={<Users />}> <Route path="/" element={<UsersIndex />} /> <Route path=":id" element={<UserProfile />} /> <Route path="me" element={<OwnUserProfile />} /> </Route> </Routes> </BrowserRouter> ); } function Users() { return ( <div> <nav> <Link to="me">My Profile</Link> </nav> <Outlet /> </div> ); }
The <Outlet> element is used as a placeholder. In this case an <Outlet>enables the Users component to render its child routes. Thus the<Outlet> element will render either a <UserProfile> or <OwnUserProfile> element depending on the current location.
Thus the best way this element can be used is in layouts. You can simply create multiple layouts, for e.g.- the Dashboard Layout(for the profile and members page) or the Main Layout(for login and logout, basically when the user is not signed in). Finally, you can simply inject whichever component one needs depending on its route rather than wrapping each route component in a parent layout component like:
<Route path="/" element={<DashboardLayout />}> <Route path="/" element={<HomePage />} /> <Route path=":id" element={<UserProfile />} /> <Route path="me" element={<OwnUserProfile />} /> </Route>
import { BrowserRouter, Link, Outlet, useRoutes } from 'react-router-dom'; function App() { // The <BrowserRouter> element is removed from App because the // useRoutes hook needs to be in the context of a <BrowserRouter> // element. This is a common pattern with React Router apps that // are rendered in different environments. To render an <App>, // you'll need to wrap it in your own <BrowserRouter> element. let element = useRoutes([ // A route object has the same properties as a <Route> // element. The `children` is just an array of child routes. { path: '/', element: <Home /> }, { path: 'users', element: <Users />, children: [ { path: '/', element: <UsersIndex /> }, { path: ':id', element: <UserProfile /> }, { path: 'me', element: <OwnUserProfile /> }, ] } ]); return element; } function Users() { return ( <div> <nav> <Link to="me">My Profile</Link> </nav> <Outlet /> </div> ); }
React Router v6 ships with an awesome API for routing that uses plain JavaScript objects to declare your routes. In fact, if you look at the source of <Routes>, you’ll see that it’s really just a tiny wrapper around a hook that is at the heart of the router’s matching algorithm: useRoutes.
The useRoutes hook is a first-class API for routing that lets you declare and compose your routes using JavaScript objects instead of React elements. Continuing with the example above, let’s see what it looks like with useRoutes.
The useRoutes hook accepts a (possibly nested) array of JavaScript objects that represent the available routes in your app. Each route has a path, element, and (optionally) children, which is just another array of routes.
This nested array of Javascript objects keeps the code DRY and improves the readability of the code.
The object-based route configuration may look familiar if you were using the react-router-config package in v5. In v6, this configuration format has been promoted to a first-class API in core and the react-router-config package will be deprecated.
Moreover, the layout example in the Outlet section can be simplified as follows:
let element = useRoutes([ { path: '/', element: <DashboardLayout/>, children: [ { path: '/', element: <HomePage/> }, { path: ':id', element: <UserProfile /> }, { path: 'me', element: <OwnUserProfile /> }, ] } ]);
Ref forwarding is a cool technique for automatically passing a ref through a component to one of its children. It gives the child component a reference to a DOM element created by its parent component. This then allows the child to read and modify that element anywhere it is being used.
Before We show you how to ‘forward’ refs lets first learn what they are and how to create them.
To create a ref, use the React function called React.createRef(). These refs can then be attached to React elements via the ref attribute. Refs are somewhat similar to state. On assigning refs to instance properties of that component we can ensure that they can be referenced anywhere in the component. Check the example below:
class MyComponent extends React.Component { constructor(props) { super(props); this.newRef = React.createRef(); //newRef is now available for use throughout our component } ... } class MyComponent extends React.Component { ... render() { return <div ref={this.myRef} />; } }
Here We created a ref called newRef and and attached it to the div element in the MyComponent component. As a result, We now have the ability to update the div without changing state.
This is the significance of using refs as you can update and modify elements without using state variables that result in the re-rendering of components.
A few points of significance directly from the documentation:
Let’s imagine you have an input component. In some parts of your application, you may want the cursor focused on it when a user clicks a button. It makes more sense to modify only that particular instance of the input component without changing the state (via refs), rather than changing the state (via props) which will cause the component to re-render every-time. Similarly, you can use refs to control the state of music or video players (pause, play, stop) without them re-rendering anytime you click a button (change the state).
Think about a Medium clap button. A quick way to implement a similar feature would be to increment the count value stored in the state every time a user clicks a clap. However, this may not be very efficient. Every time a user clicks the clap button it will re-render, and if you are sending a network request to store the value in a server it will get sent as many times as the button is clicked. With refs, you can target that particular node and increment it every time a user clicks the button without causing a re-render and finally, you can send one request to our server with the final value.
You can use refs to trigger animation between elements that rely on themselves for their next state but exist in different components (this concept is called ref forwarding). Refs can also be used to simplify integration with third-party DOM libraries and managing multistep form value states etc.
Now let’s move to the technique of ref forwarding:
Ref forwarding is a technique that automatically passes a ref through a component to one of its children. Ref forwarding is very useful when building reusable component libraries. forwardRef is the function used to pass the ref to a child component. Let’s check out an example below:
function SampleButton(props) { return ( <button className="button"> {props.children} </button> ); }
The SampleButton() component is a modified button that will be used throughout the application in a similar manner as a regular DOM button, therefore accessing its DOM node may be unavoidable for managing focus, selection, or animations related to it.
In the example below, SampleComponent() uses React.forwardRef to obtain the ref passed to it, and then forward it to the DOM button that it renders:
const SampleButton = React.forwardRef((props, ref) => ( <button ref={ref} className="button"> {props.children} </button> )); const ref = React.createRef(); <SampleButton ref={ref}>Click me!</SampleButton>;
Now that We’ve wrapped the SampleButton component with the forwardRef method, components using it can get a ref to the underlying button DOM node and access it if necessary – just like if they used a DOM button directly.
Here’s a clarification for the code above:
We have just covered the basics of these very extensive topics. Hope you try them out in your coming React projects.
For more information and to develop web application using React JS, Hire React Developer from us as we give you a high-quality product by utilizing all the latest tools and advanced technology. E-mail us any clock at – hello@hkinfosoft.com or Skype us: “hkinfosoft”. To develop custom web apps using React JS, please visit our technology page.
Content Source:
We are excited to announce the release of Node.js 16 today! Highlights include the update of the V8 JavaScript engine to 9.0, prebuilt Apple Silicon binaries, and additional stable APIs.
You can download the latest release from https://nodejs.org/en/download/current/, or use Node Version Manager on UNIX to install with nvm install 16
. The Node.js blog post containing the changelog is available at https://nodejs.org/en/blog/release/v16.0.0.
Initially, Node.js 16 will replace Node.js 15 as our ‘Current’ release line. As per the release schedule, Node.js 16 will be the ‘Current’ release for the next 6 months and then promoted to Long-term Support (LTS) in October 2021. Once promoted to long-term support the release will be designated the codename ‘Gallium’.
As a reminder – Node.js 12 will remain in long-term support until April 2022, and Node.js 14 will remain in long-term support until April 2023. Node.js 10 will go End-of-Life at the end of this month (April 2021). More details on our release plan/schedule can be found in the Node.js Release Working Group repository.
As always a new version of the V8 JavaScript engine brings performance tweaks and improvements as well as keeping Node.js up to date with JavaScript language features. In Node.js v16.0.0, the V8 engine is updated to V8 9.0 — up from V8 8.6 in Node.js 15.
This update brings the ECMAScript RegExp Match Indices, which provide the start and end indices of the captured string. The indices array is available via the .indices
property on match objects when the regular expression has the /d
flag.
> const matchObj = /(Java)(Script)/d.exec('JavaScript'); undefined > matchObj.indices [ [ 0, 10 ], [ 0, 4 ], [ 4, 10 ], groups: undefined ] > matchObj.indices[0]; // Match [ 0, 10 ] > matchObj.indices[1]; // First capture group [ 0, 4 ] > matchObj.indices[2]; // Second capture group [ 4, 10 ]
The Timers Promises API provides an alternative set of timer functions that return Promise objects, removing the need to use util.promisify()
.
import { setTimeout } from 'timers/promises'; async function run() { await setTimeout(5000); console.log('Hello, World!'); } run();
Added in Node.js v15.0.0 by James Snell (https://github.com/nodejs/node/pull/33950), in this release, they graduate from experimental status to stable.
The nature of our release process means that new features are released in the ‘Current’ release line approximately every two weeks. For this reason, many recent additions have already been made available in the most recent Node.js 15 releases, but are still relatively new to the runtime.
Some of the recently released features in Node.js 15, which will also be available in Node.js 16, include:
AbortController
implementation based on the AbortController Web API(buffer.atob(data))
and btoa (buffer.btoa(data))
implementations for compatibility with legacy web platform APIsNode.js provides pre-built binaries for several different platforms. For each major release, the minimum toolchains are assessed and raised where appropriate.
Node.js v16.0.0 will be the first release where we ship prebuilt binaries for Apple Silicon. While we’ll be providing separate tarballs for the Intel (darwin-x64)
and ARM (darwin-arm64)
architectures the macOS installer (.pkg)
will be shipped as a ‘fat’ (multi-architecture) binary.
The production of these binaries was made possible thanks to the generosity of MacStadium donating the necessary hardware to the project.
On our Linux-based platforms, the minimum GCC level for building Node.js 16 will be GCC 8.3. Details about the supported toolchains and compilers are documented in the Node.js BUILDING.md file.
As a new major release, it’s also the time where we introduce new runtime deprecations. The Node.js project aims to minimize the disruption to the ecosystem for any breaking changes. The project uses a tool named CITGM (Canary in the Goldmine), to test the impact of any breaking changes (including deprecations) on a large number of the popular ecosystem modules to provide additional insight before landing these changes.
Notable deprecations in Node.js 16 include the runtime deprecation of access to process.binding()
for a number of the core modules, such as process.binding('http_parser')
.
For more information and to develop web applications using Node JS, Hire Node Developer from us as we give you a high-quality product by utilizing all the latest tools and advanced technology. E-mail us any clock at – hello@hkinfosoft.com or Skype us: “hkinfosoft”. To develop custom web apps using Node JS, please visit our Hire Node Developer technology page.
Content Source:
There are many ways one can structure an Angular app. But this is how we structure our applications for extensive flexibility, scalability, and small initial bundle size.
Fig-1: Preferred Directory Structure
Pic courtesy: javascript.plainenglish.io
Core directory is the place where you put singleton services, injection tokens, constants, app configurations, pipes, interceptors, guards, auth service, utils, etc. that will be used app-wide. If there is something which is specific to the application itself, deployment, CI/CD, API, and the Developer – chances are, it belongs to the core.
Fig-1: Example Core directory
Pic courtesy: javascript.plainenglish.io
Business features live in this directory. Make a module per feature. That module can contain components, directives, pipes, services, interfaces, enums, utils, and so on. The idea is to keep things close. So, a pipe, that is solely used in the Speakers module should not be defined in the global scope or inside Core. The same goes for any other angular building block required by this module only.
Fig-2: An example feature module
Pic courtesy: javascript.plainenglish.io
Components are prefixed according to the module name e.g.- if the module name is SpeakersModule, components would be named SpeakerAbcComponent, SpeakerXyzComponent etc.
Keep the component tree inside the directory flat. That means, if SpeakerListComponent is the parent and SpeakerListItemComponent is child, do not create speaker-list-item component inside the speaker-list directory. The prefixed naming should be clear to indicate such a relation. The idea is to be able to see what components reside in the module at a glance.
Feature modules can import other features and obviously from shared modules.
Consider shared modules a minWe library for your UWe components. They are not specific to a single business feature. They should be super dumb that you can take all the components, drop in another angular project, and expect to work (given the dependencies are met). You might already know that wrapping UWe components provided by other libraries such as Material, ng-zorro-antd, ngx-bootstrap, etc. is a good practice. It protects you from their APWe changes and allows you to replace the underlying library if required. Components in shared modules are a good place for such wrapping.
Fig-3: Example Shared Directory
Pic courtesy: javascript.plainenglish.io
Do not make a giant SharedModule, rather granularize each atomic feature into its own module (see Fig-3). Criss-cross import of atomic shared modules is allowed, but try to minimize as best as possible. To bring a flavor of a tiny library, you could even prefix the directories & modules with your angular application’s custom prefix (by default it is app ).
Pages directory is the most interesting part of this structure. Think of it like a sink, where feature modules fall into but nothing comes out (i.e- no exported member). In these modules, you do not declare any component other than the page.
Fig-4: Example Page Module
Pic courtesy: javascript.plainenglish.io
Page controllers have no business logic. They are merely the presenter and orchestrates components from business feature modules. Let’s say – home page. It will contain a header, a hero section, articles, comments, contact, etc. sections – all coming from respective feature modules!
@NgModule({ declarations: [HomePageComponent], imports: [ CommonModule, ArticlesModule, CommentsModule, ContactModule, HeadersModule, HomePageRoutingModule, ], }) export class HomePageModule {}
How a fictional home-page.component.ts might look like:
<app-header-default></app-header-default> <main class="container"> <app-hero-content></app-hero-content> <app-article-list></app-article-list> <app-comment-list-latest></app-comment-list-latest> <app-contact-form></app-contact-form> </main> <app-footer-default></app-footer-default>
They can take help from a page-specific service that combines data and state for that page only. You should provide such service to the page component and NOT in root. Otherwise, the state may persist even after you navigate away from the page because the page component will get destroyed but not the page service.
// home-page.service.ts @Injectable() export class HomePageService {} // home-page.component.ts @Component({ ... providers: [HomePageService] } export class HomePageComponent { constructor(private homePageService: HomePageService){} }
The most important purpose of page modules is that each module is loaded lazily to make the app performant and lite.
Pro-tip: If you define a single page component per module, then you can claim a further reduction in the initial bundle size. This practice also organizes all routes in a single source (namely AppRoutingModule) which is easier to manage. Then, your app-routing.module.ts file may look like this:
const appRoutes: Routes = [ { path: '', loadChildren: () => import('./pages/home-page/home-page.module').then((m) => m.HomePageModule), }, { path: 'home', redirectTo: '', pathMatch: 'full', }, { path: 'products/:id', // <-------- NOTE 1. Child route loadChildren: () => import('./pages/product-details-page/product-details-page.module').then((m) => m.ProductDetailsPageModule), }, { path: 'products', // <--------- NOTE 2. Parent route loadChildren: () => import('./pages/product-list-page/product-list-page.module').then((m) => m.ProductListPageModule), }, { path: 'checkout/pay', loadChildren: () => import('./pages/checkout-payment-page/checkout-payment-page.module').then((m) => m.CheckoutPaymentPageModule), }, { path: 'checkout', loadChildren: () => import('./pages/checkout-page/checkout-page.module').then((m) => m.CheckoutPageModule), }, { path: '**', loadChildren: () => import('./pages/not-found-page/not-found-page.module').then((m) => m.NotFoundPageModule), }, ]
Notes 1 & 2: Since route declarations are parsed top-to-bottom, be sure to declare child paths before the parent path. This will ensure lazy-loading chunks fetched correctly. Otherwise, if you define the parent route first, then visiting any child route will also load the parent route’s module chunk unnecessarily. You can see the difference in DevTools. Here is my experiment when We put parent route first (Fig-5.1) VS child route first (Fig-5.2)
Fig-5.1: When /products declared BEFORE /products/:id in routes config
Pic courtesy: javascript.plainenglish.io
Fig-5.2: When /products declared AFTER /products/:id in routes config
Pic courtesy: javascript.plainenglish.io
For more information and to develop web application using Angular, Hire Angular Developer from us as we give you a high-quality product by utilizing all the latest tools and advanced technology. E-mail us any clock at – hello@hkinfosoft.com or Skype us: “hkinfosoft”. To develop web application using Angular, please visit our technology page.
Content Source:
Making frontend applications is not as simple as it used to be. Frontend frameworks like React and Vue.js rely heavily on APIs. This adds complexity to our app because we need to manage how we call these APIs. One solution is to simplify the process by writing clean API calls.
But wait, what are “clean API calls”? To me, that means the proper structuring of API calls, making them easy to read and maintain. First, we do this by utilizing the single-responsibility principle. Each function must have a single responsibility, and with this principle in mind, we need to separate the logic for each endpoint.
The other thing we try to consider is the DRY principle (“Don’t Repeat Yourself”). This is very important – arguably more so in the case of frontend API providers – because it gives a sense of tidiness in the code, thus improving readability. we use Axios because it gives features such as interceptors, defaults, etc. It reduces the amount of boilerplate code you need to write for each API endpoint.
There are many ways to achieve this. You can either use the Fetch API or you can use a third-party library called Axios. By the title of this article, you can guess that we prefer Axios. Why? Let’s weigh in on the pros and cons.
What we like most about Axios is that it is very simple to use. The programming API is so easy to use that we have gotten really used to it. Well, this might be too personal of a preference, but you can try it yourself. we have used jQuery’s AJAX and the Fetch API, and we would rank Axios above all of them – although not by too large of a margin since all three of them are nice to work with.
Honesty, you wouldn’t think about this feature until you needed it. we mean, most people have modern browsers, but if some of your customers aren’t most people, they might not be able to use your app if it isn’t backward-compatible. The Fetch API is relatively new and old browsers aren’t capable of using it. Otherwise, libraries like Axios and jQuery’s AJAX are built on top of JavaScript’s XMLHttpRequest. For those of you who are wondering, XMLHttpRequest is an old version of JavaScript’s built-in HTTP calling mechanism.
You can do a lot with Axios – a whole lot. For example, as of the writing of this article, the Fetch API does not have built-in request/response interceptors. You have to use third parties. Compared to Fetch, writing clean APIs using Axios is very simple. Axios already has so many built-in conveniences. To name a few, you can set default headers and default base URLs using Axios.
we have used Axios for long enough to understand that this library can be overkill for small apps. If you only need to use its GET and POST-APIs, you probably are better off with the Fetch API anyway. Fetch is native to JavaScript, whereas Axios is not. This brings us to the next point.
This second point corresponds to the first one perfectly. One of the main reasons we avoid the use of Axios for small apps is the fact that it bloats your production build size. Sure, you might not notice a size spike for large apps like in e-commerce and such. But you will notice a huge increase if you are making a simple portfolio site. The lesson to be learned? Use the right tools for the right job.
Look, let me just start by saying that this third point is really subjective and some people might have opposite views. Axios is a third party. Yes, you read that right. Unlike Fetch, it is not native to the browser. You are depending on the community to maintain your precious app. Then again, most apps these days do use open-source products. So would it be a problem? Not really. Again, this is a preference. we are not advising you to reinvent the wheel. Just understand that you don’t own the wheel.
Axios is available in multiple JavaScript repositories. You can access it using yarn and NPM. If you are using regular HTML, you can import it from CDNs like jsDelivr, Unpkg, or Cloudflare.
Assuming you are using NPM, we need to install Axios using this command:
npm install -S axios
If there are no errors in the installation, you can continue to the next step. You can check alternative installation methods on GitHub.
What are Axios clients? Clients are how we set default parameters for each API call. We set our default values in the Axios clients, then we export the client using JavaScript’s export default. Afterward, we can just reference the client from the rest of our app.
First, make a new file preferably named apiClient.js and import Axios:
import axios from 'axios';
Then make a client using axios.create:
const axiosClient = axios.create({ baseURL: `https://api.example.com`, headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' } });
As you can see, we initiated the base URLs and default headers for all our HTTP calls.
When calling interacting APIs – especially when there is authentication involved – you will need to define conditions when your call is unauthorized and make your application react appropriately. Interceptors are perfect for this use case.
Let’s say that we need our application to redirect us to our home page when our cookies expire, and when our cookies expire, the API will return a 401 status code. This is how you would go about it:
axiosClient.interceptors.response.use( function (response) { return response; }, function (error) { let res = error.response; if (res.status == 401) { window.location.href = “https://example.com/login”; } console.error(“Looks like there was a problem. Status Code: “ + res.status); return Promise.reject(error); } );
Simple, right? After you’ve defined your client and attached an interceptor, you just need to export your client to be used on other pages.
After configuring your Axios client, you need to export it to make it available for the entire project. You can do this by using the export default feature:
export default { axiosClient );
Now we have made our Axios client available for the entire project. Next, we will be making API handlers for each endpoint.
Before we continue, we thought it would be useful to show you how to arrange your subfolders. Instead of writing a long comprehensive explanation, we think it would be better for me to give you an image of what we are talking about:
How I would arrange my folders. Pic courtesy: betterprogramming.pub
This assumes we will have admin, user, and product endpoints. We will home the apiClient.js file inside the root of the network folder. The naming of the folder or even the structure is just our personal preference.
The endpoints will be put inside a lib folder and separated by concerns in each file. For example, for authentication purposes, user endpoints would be put inside the user file. Product-related endpoints would be put inside the product file.
Now we will be writing the API handler. Each endpoint will have its asynchronous function with custom parameters. All endpoints will use the client we defined earlier. In the example below, we will write two API handlers to get new products and add new products:
import { axiosClient } from "../apiClient"; export function getProduct(){ return axiosClient.get('/product'); } export function addProduct(data){ return axiosClient.post('/product', JSON.stringify(data)); }
This pretty much sums up how we would write an API handler, and as you can see, each API call is clean and it all applies the single-responsibility principle. You can now reference these handlers on your main page.
Assuming that you are using an NPM project for all of this, you can easily reference your JavaScript API handlers using the import method. In this case, we will be using the getProduct endpoint:
import { getProduct } from "../network/lib/product"; getProduct() .then(function(response){ // Process response and // Do something with the UI; });
There you have it: a clean no-fuss API handler. You’ve successfully made your app much more readable and easier to maintain.
For more information and to develop your web app using front-end technology, Hire Front-End Developer from us as we give you a high-quality solution by utilizing all the latest tools and advanced technology. E-mail us any clock at – hello@hkinfosoft.com or Skype us: “hkinfosoft“. To develop your custom website using JS, please visit our technology page.
Content Source:
In this post, we will cover five simple React hooks that you will find handy in any project. These hooks are useful no matter the features of the application. For each hook, we will provide the implementation and the client code sample.
Web applications use modals extensively and for various reasons. When working with modals, you quickly realize that managing their state is a tedious and repetitive task. And when you have code that’s repetitive and tedious, you should take time to abstract it. That’s what useModalState
does for managing modal states.
Many libraries provide their version of this hook, and one such library is Chakra UI. If you want to learn more about Chakra UI, check out my blog post here.
The implementation of the hook is very simple, even trivial. But in my experience, it pays off using it rather than rewriting the code for managing the modal’s state each time.
import React from "react"; import Modal from "./Modal"; export const useModalState = ({ initialOpen = false } = {}) => { const [isOpen, setIsOpen] = useState(initialOpen); const onOpen = () => { setIsOpen(true); }; const onClose = () => { setIsOpen(false); }; const onToggle = () => { setIsOpen(!isOpen); }; return { onOpen, onClose, isOpen, onToggle }; };
And here’s an example of client code using the hook:
const Client = () => { const { isOpen, onToggle } = useModalState(); const handleClick = () => { onToggle(); }; return ( <div> <button onClick={handleClick} /> <Modal open={isOpen} /> </div> ); }; export default Client;
useConfirmationDialog
is another modal-related hook that we use quite often. It’s a common practice to ask users for confirmations when performing sensitive actions, like deleting records. So it makes sense to abstract that logic with a hook. Here’s a sample implementation of the useConfirmationDialog
hook:
import React, { useCallback, useState } from 'react'; import ConfirmationDialog from 'components/global/ConfirmationDialog'; export default function useConfirmationDialog({ headerText, bodyText, confirmationButtonText, onConfirmClick, }) { const [isOpen, setIsOpen] = useState(false); const onOpen = () => { setIsOpen(true); }; const Dialog = useCallback( () => ( <ConfirmationDialog headerText={headerText} bodyText={bodyText} isOpen={isOpen} onConfirmClick={onConfirmClick} onCancelClick={() => setIsOpen(false)} confirmationButtonText={confirmationButtonText} /> ), [isOpen] ); return { Dialog, onOpen, }; }
And here’s an example of the client code:
import React from "react"; import { useConfirmationDialog } from './useConfirmationDialog' function Client() { const { Dialog, onOpen } = useConfirmationDialog({ headerText: "Delete this record?", bodyText: "Are you sure you want delete this record? This cannot be undone.", confirmationButtonText: "Delete", onConfirmClick: handleDeleteConfirm, }); function handleDeleteConfirm() { //TODO: delete } const handleDeleteClick = () => { onOpen(); }; return ( <div> <Dialog /> <button onClick={handleDeleteClick} /> </div> ); } export default Client;
One thing to note here is that this implementation works fine as long as your confirmation modal doesn’t have any controlled input elements. If you do have controlled inputs, it’s best to create a separate component for your modal. That’s because you don’t want the content of the modal, including those inputs, to re-render each time the user types something.
Properly handling async actions in your application is trickier than it seems at first. There are multiple state variables that you need to keep track of while the task is running. You want to keep the user informed that the action is processing by displaying a spinner. Also, you need to handle the errors and provide useful feedback when they happen. So it pays off to have an established framework for dealing with async tasks in your React project. And that’s where you might find useAsync
useful. Here’s an implementation of the useAsync
hook:
export const useAsync = ({ asyncFunction }) => { const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const [result, setResult] = useState(null); const execute = useCallback( async (...params) => { try { setLoading(true); const response = await asyncFunction(...params); setResult(response); } catch (e) { setError(e); } setLoading(false); }, [asyncFunction] ); return { error, result, loading, execute }; };
The client code:
import React from "react"; export default function Client() { const { loading, result, error, execute } = useAsync({ asyncFunction: someAsyncTask, }); async function someAsyncTask() { // perform async task } const handleClick = () => { execute(); }; return ( <div> {loading && <p>loading</p>} {!loading && result && <p>{result}</p>} {!loading && error?.message && <p>{error?.message}</p>} <button onClick={handleClick} /> </div> ); }
The hook is not hard to write yourself and that’s what we often do. But it might make sense for you to use a more mature library implementation instead. Here’s a great option.
Form validation is another part of React applications that people often find tedious. With that said, there are plenty of great libraries to help with forms management in React. One great alternative is formik. However, each of those libraries has a learning curve. And that learning curve often makes it not worth using in smaller projects. Particularly if you have others working with you and they are not familiar with those libraries.
But it doesn’t mean we can’t have simple abstractions for some of the code we often use. One such piece of code that we like to abstract is error validation. Checking forms before submitting to API and displaying validation results to the user is a must-have for any web application. Here’s an implementation of a simple useTrackErrors
hook that can help with that:
import React, { useState } from "react"; import FormControl from "./FormControl"; import Input from "./Input"; import onSignup from "./SignupAPI"; export const useTrackErrors = () => { const [errors, setErrors] = useState({}); const setErrors = (errsArray) => { const newErrors = { ...errors }; errsArray.forEach(({ key, value }) => { newErrors[key] = value; }); setErrors(newErrors); }; const clearErrors = () => { setErrors({}); }; return { errors, setErrors, clearErrors }; };
And here’s the client implementation:
import React, { useState } from "react"; import FormControl from "./FormControl"; import Input from "./Input"; import onSignup from "./SignupAPI"; export default function Client() { const { errors, setErrors, clearErrors } = useTrackErrors(); const [name, setName] = useState(""); const [email, setEmail] = useState(""); const handleSignupClick = () => { let invalid = false; const errs = []; if (!name) { errs.push({ key: "name", value: true }); invalid = true; } if (!email) { errs.push({ key: "email", value: true }); invalid = true; } if (invalid) { setErrors(errs); return; } onSignup(name, email); clearErrors(); }; const handleNameChange = (e) => { setName(e.target.value); setErrors([{ key: "name", value: false }]); }; const handleEmailChange = (e) => { setEmail(e.target.value); setErrors([{ key: "email", value: false }]); }; return ( <div> <FormControl isInvalid={errors["name"]}> <FormLabel>Full Name</FormLabel> <Input onKeyDown={handleKeyDown} onChange={handleNameChange} value={name} placeholder="Your name..." /> </FormControl> <FormControl isInvalid={errors["email"]}> <FormLabel>Email</FormLabel> <Input onKeyDown={handleKeyDown} onChange={handleEmailChange} value={email} placeholder="Your email..." /> </FormControl> <button onClick={handleSignupClick}>Sign Up</button> </div> ); }
Debouncing has a broad use in any application. The most common use is throttling expensive operations. For example, preventing the application from calling the search API every time the user presses a key and letting the user finish before calling it. The useDebounce
hook makes throttling such expensive operations easy. Here’s a simple implementation that’s written using AwesomeDebounceLibrary under the hood:
import AwesomeDebouncePromise from "awesome-debounce-promise"; const debounceAction = (actionFunc, delay) => AwesomeDebouncePromise(actionFunc, delay); function useDebounce(func, delay) { const debouncedFunction = useMemo(() => debounceAction(func, delay), [ delay, func, ]); return debouncedFunction; }
And here’s the client code:
import React from "react"; const callAPI = async (value) => { // expensice API call }; export default function Client() { const debouncedAPICall = useDebounce(callAPI, 500); const handleInputChange = async (e) => { debouncedAPICall(e.target.value); }; return ( <form> <input type="text" onChange={handleInputChange} /> </form> ); }
One thing to note with this implementation: You need to ensure that the expensive function is not recreated on each render. Because that will reset the debounced version of that function and wipe out its inner state. There are two ways to achieve that:
And that’s it for this post. There are many useful hook libraries worth checking out, and if you’re interested, here’s a great place to start. While there are many helpful custom hooks out there, these five are the ones that you will find handy in any React project.
For more information and to develop web application using React JS, Hire React Developer from us as we give you a high-quality product by utilizing all the latest tools and advanced technology. E-mail us any clock at – hello@hkinfosoft.com or Skype us: “hkinfosoft”. To develop custom web apps using React JS, please visit our technology page.
Content Source:
57 Sherway St,
Stoney Creek, ON
L8J 0J3
606, Suvas Scala,
S P Ring Road, Nikol,
Ahmedabad 380049
1131 Baycrest Drive,
Wesley Chapel,
FL 33544
57 Sherway St,
Stoney Creek, ON
L8J 0J3
606, Suvas Scala,
S P Ring Road, Nikol,
Ahmedabad 380049
1131 Baycrest Drive,
Wesley Chapel,
FL 33544
© 2025 — HK Infosoft. All Rights Reserved.
© 2025 — HK Infosoft. All Rights Reserved.
T&C | Privacy Policy | Sitemap