To open a link in a new tab programmatically in React, call the window.open() method with the link as an argument, e.g., window.open('https://codingbeautydev.com'). The open() method will open the link in a new browser tab.
In the following example, we programmatically open the link in a new tab at the end of a countdown:
App.js
import { useRef, useEffect, useState } from 'react';
export default function App() {
const [timeLeft, setTimeLeft] = useState(3);
const interval = useRef();
useEffect(() => {
interval.current = setInterval(() => {
// Decrease "timeLeft" by 1 every second
setTimeLeft((prev) => prev - 1);
}, 1000);
return () => clearInterval(interval.current);
}, []);
useEffect(() => {
// Open the link in a new tab when the countdown ends
if (timeLeft === 0) {
clearInterval(interval.current);
// π Open link in new tab programmatically
window.open('https://codingbeautydev.com', '_blank', 'noreferrer');
}
}, [timeLeft]);
return (
<div>
The link will open in <b>{timeLeft}</b> second(s)
</div>
);
}
We use the open() method of the window object to programmatically open a link in a new tab. This method has three optional parameters:
url: The URL of the page to open in a new tab.
target: like the target attribute of the <a> element, this parameterβs value specifies where to open the linked document, i.e., the browsing context. It accepts all the values the target attribute of the <a> element accepts.
windowFeatures: A comma-separated list of feature options for the window. noreferrer is one of these options.
Passing _blank to the target parameter makes the link get opened in a new tab.
Open link in new tab on button click
Being able to open a link in a new tab programmatically means that we can use a button in place of an anchor link to open a URL on click. We’d just set an onClick event listener on the button element and call the window.open() method in the listener.
For example:
App.js
export default function App() {
const openInNewTab = (url) => {
window.open(url, '_blank', 'noreferrer');
};
return (
<div>
<p>Visit codingbeautydev.com in a new tab</p>
<button
role="link"
onClick={() => openInNewTab('https://codingbeautydev.com')}
>
Visit
</button>
</div>
);
}
To open a link in a new tab in React, create an anchor (<a>) element and set its target attribute to _blank, e.g., <a href="https://codingbeautydev.com" target="_blank">Link</a>. The _blank value specifies that the link should be opened in a new tab.
The target property of the anchor element specifies where to open the linked document. By default target has a value of _self, which makes the linked page open in the same frame or tab where it was clicked. To make the page open in a new tab, we set target to _blank.
We also set the rel prop to noreferrer for security purposes. It prevents the opened page from gaining any information about the page that it was opened from.
Open link in new tab programmatically
We can use the window.open() method to programmatically open a link in a new tab in React, e.g., window.open(url, '_blank', 'noreferrer').
For example:
App.js
import { useRef, useEffect, useState } from 'react';
export default function App() {
const [timeLeft, setTimeLeft] = useState(3);
const interval = useRef();
useEffect(() => {
interval.current = setInterval(() => {
// Decrease "timeLeft" by 1 every second
setTimeLeft((prev) => prev - 1);
}, 1000);
return () => clearInterval(interval.current);
}, []);
useEffect(() => {
// Open the link in a new tab when the countdown ends
if (timeLeft === 0) {
clearInterval(interval.current);
// π Open link in new tab programmatically
window.open('https://codingbeautydev.com', '_blank', 'noreferrer');
}
}, [timeLeft]);
return (
<div>
The link will open in <b>{timeLeft}</b> second(s)
</div>
);
}
We use the open() method of the window object to programmatically open a link in a new tab. This method has three optional parameters:
url: The URL of the page to open in a new tab.
target: like the target attribute of the <a> element, this parameterβs value specifies where to open the linked document, i.e., the browsing context. It accepts all the values the target attribute of the <a> element accepts.
windowFeatures: A comma-separated list of feature options for the window. noreferrer is one of these options.
Passing _blank to the target parameter makes the link get opened in a new tab.
Open link in new tab on button click
Being able to open a link in a new tab programmatically means that we can use a button in place of an anchor link to open a URL on click. We’ll just set an onClick event listener on the button element and call the window.open() method in the listener.
For example:
App.js
export default function App() {
const openInNewTab = (url) => {
window.open(url, '_blank', 'noreferrer');
};
return (
<div>
<p>Visit codingbeautydev.com in a new tab</p>
<button
role="link"
onClick={() => openInNewTab('https://codingbeautydev.com')}
>
Visit
</button>
</div>
);
}
To check if a string contains uppercase letters in JavaScript, call the test() method on this regular expression /[A-Z]/, i.e., /A-Z/.test(str). test() will return true if the string contains any uppercase letters. Otherwise, it will return false.
The RegExptest() method searches a string for matches with a specified regular expression and returns true if any are found. Otherwise, it returns false.
The forward slashes (/ /) indicate the start and end of the regular expression.
The square brackets ([ ]) match any one of a given set of characters. The A-Z pattern specifies that these characters be all the letters from A to Z in uppercase. So the complete regular expression matches any capital letter in the string.
Check if string contains only uppercase letters
To check if a string contains only uppercase letters, we’ll need to use a slightly different regex: /^[A-Z]+$/.
Let’s look into the differences in this new regex:
The ^ character specifies that the pattern must be at the start of the string. Conversely, the $ character indicates that the pattern must be at the end.
The + character matches one or more consecutive occurrences of the preceding pattern in the string.
So matches for the regex will only be found in a string that contains a group of consecutive uppercase letters from the start to the end of the string – a string with only uppercase letters.
Check out this cheat sheet from the MDN docs for a comprehensive guide to regular expression syntax.
Stringmatch() method
An alternative to RegExptest() is the Stringmatch() method. Instead of calling test() on the regex, we call match() on the string with the regex as an argument.
We pass the result of match() to the Boolean() constructor to convert it to a Boolean. Boolean converts truthy values to true, and falsy values to false.
In JavaScript, there are six falsy values: undefined, null, NaN, 0, '' (empty string), and false. Every other value is truthy.
We used the optional chaining operator (?.) on the string variable. If the variable is undefined or null, this operator will prevent the method call and return undefined instead of throwing an error.
To split a string every N characters in JavaScript, call the match() method on the string, passing as an argument this regular expression: /.{1, N}g/. The match() method will return an array containing substrings that each has N characters.
The Stringmatch() method matches a string against a regular expression and returns an array of all the matches.
The forward slashes / / indicate the start and end of the regular expression.
The . (dot) metacharacter matches any single character in the string.
The braces in the form {min, max} match at least min characters and at most max characters of the pattern preceding it. In our case, that pattern is the . character, min is 1, and max is 4, meaning that .{1, 4} matches between 1 and 4 characters in the string.
We use the g (global) flag to make every occurrence of the pattern in the string get matched. It makes the regex keep splitting the string by the N characters until it gets to the end.
Without the g flag, only the first instance of the pattern will be matched.
const str = 'codingbeauty';
// "g" flag not specified
const result = str.match(/.{1,4}/) ?? [];
// [ 'codi' ... ] (single-item array)
console.log(result);
For a comprehensive guide to regular expression syntax, check out this cheat sheet from the MDN docs.
If there are no matches for the regex in the string, match() returns null. This is why we use the null coalescing operator (??) to return an empty array ([]) in such a case.
If the string’s length is not a multiple of N, the last element in the array will be less than N.
const str = 'codingbeautydev';
const result = str.match(/.{1,4}/g) ?? [];
// π Last item is less than 4 characters long
console.log(result); // [ 'codi', 'ngbe', 'auty', 'dev' ];
Split string every N characters with for loop
Alternatively, we can use a for loop to split a string every N characters.
function splitString(str, N) {
const arr = [];
for (let i = 0; i < str.length; i += N) {
arr.push(str.substring(i, i + N));
}
return arr;
}
// [ 'codi', 'ngbe', 'auty' ]
console.log(splitString('codingbeauty', 4));
// [ 'codi', 'ngbe', 'auty', 'dev' ]
console.log(splitString('codingbeautydev', 4));
Our splitString() function takes the string and the length each substring should have as arguments.
We use the for loop to iterate over the string in increments of N. On each iteration, we call the Stringsubstring() method to get a substring between index i and index i + N exclusive in the string, and add the substring to the resulting array.
Split string every N characters with reduce() method
Every time you see a for loop used to process input to get output, it’s a sign that the code can be refactored to be made more functional and declarative, using one or more Array methods.
Check out this method to split a string every N characters, where we use the reduce() method to create some nice functional magic:
I don’t recommend this though; as far as performance is concerned, it’s significantly (over 30 times) slower than the previous method, and might be harder to understand. I included it because it’s an elegant one-liner solution that works.
React now has concurrency support with the release of version 18. There are numerous features now that help to make better use of system resources and boost app performance. One such feature is the useDefferedValue hook, in this article we’re going to learn about useDeferredValue and understand the scenarios where we can use it.
Why do we need useDefferedValue?
Before we can see this hook in action, we need to understand something about how React manages state and updates the DOM.
Here we create a state variable with the useState hook, and a computed value (computedValue) derived from the state. We use the useMemo hook to recalculate the computed value only when the state changes.
So when the value of the input field changes, the name state variable is updated and the computed value is recomputed before the DOM is updated.
This usually isn’t an issue, but sometimes this recalculation process involves a large amount of computation and takes a long time to finish executing. This can reduce performance and degrade the user experience.
For example, we could be developing a feature that lets a user search for an item in a gigantic list:
In this example, we have a query state variable used to filter through a huge list of items. The longer the list, the more time it will take for the filtering to finish and the list variable to be updated for the DOM update to complete.
So when the user types something in the input field, the filtering will cause a delay in the DOM update and it’ll take time for the text in the input to reflect what the user typed immediately. This slow feedback will have a negative effect on how responsive your app feels to your users.
I simulated the slowness in the demo below so you can better understand this problem. There are only a few search results for you to properly visualize it, and they’re each just the uppercase of whatever was typed into the input field.
In this demo, I am typing each character one after the other as quickly as I can, but because of the artificial slowness, it takes about a second for my keystroke to change the input text.
useDeferredValue in action
This is a situation where the useDeferredValue hook is handy. useDeferredValue() accepts a state value as an argument and returns a copy of the value that will be deferred, i.e., when the state value is updated, the copy will not update accordingly until after the DOM has been updated to reflect the state change. This ensures that urgent updates happen and are not delayed by less critical, time-consuming ones.
In the example above, our previous code has been modified to use the useDeferredValue hook. As before, the query state variable will be updated when the user types, but this time, useMemo won’t be invoked right away to filter the large list, because now deferredQuery is the dependency useMemo is watching for changes, and useDeferredValue ensures that deferredQuery will not be updated until after query has been updated and the component has been re-rendered.
Since useMemo won’t be called and hold up the DOM update from the change in the query state, the UI will be updated without delay and the input text will change once the user types. This solves the responsiveness issue.
After the query state is updated, thendeferredQuery will be updated, causing useMemo to filter through the large list and recompute a value for the list variable, updating the list of items shown below the input field.
As you can see in the demo, the text changes immediately as I type, but the list lags behind and updates sometime later.
If we keep changing the input field’s text in a short period (e.g., by typing fast), the deferredQuery state will remain unchanged and the list will not be updated. This is because the query state will keep changing before useDeferredValue can be updated, so useDeferredValue will continue to delay the update until it has time to set deferredQuery to the latest value of query and update the list.
Here’s what I mean:
This is quite similar to debouncing, as the list is not updated till a while after input has stopped.
Tip
Sometimes in our apps, we’ll want to perform an expensive action when an event occurs. If this event happens multiple times in a short period, the action will be done as many times, decreasing performance. To solve this, we can set a requirement that the action only be carried out “X” amount of time since the most recent occurrence of the event. This is called debouncing.
For example, in a sign-up form, instead of sending a request once the user types to check for a duplicate username in the database, we can make the request get sent only 500 ms since the user last typed in the username input field (or of course, we could perform this duplicate check after the user submits the form instead of near real-time).
Since the useDeferredValue hook defers updates and causes additional re-render, it’s important that you don’t overuse it as this could actually cause the performance problems we’re trying to avoid, as it forces React to do extra re-renders in your app. Use it only when you have critical updates that should happen as soon as possible without being slowed down by updates of lower priority.
Conclusion
The useDeferred value accepts a state variable and returns a copy of it that will not be updated until the component has been re-rendered from an update of the original state. This improves the performance and responsiveness of the app, as time-consuming updates are put off to a later time to make way for the critical ones that should be shown in the DOM without delay for the user to see.
Remove empty strings from array with filter() method
To remove empty strings from an array in JavaScript, call the filter() method on the array, passing a callback that returns true for every element in the array that is not an empty string. The filter() method will return a new array excluding the empty strings.
The Arrayfilter() method creates a new array filled with elements that pass a test specified by a callback function. It doesn’t modify the original array.
In our example, each element in the array will only pass the test if it is not an empty string (''). So no empty strings are included in the resulting array.
Remove empty strings from array with loop
Here’s an alternative way to remove empty strings from an array in JavaScript.
We create an array variable (noEmptyStrings) that will store the elements in the original array that are not empty strings. Then we use a for..of loop to iterate over the array. For each element, we check if it is a non-empty string, using an if statement. If it is, we add it to the array variable. At the end of the loop, we’ll have an array containing no empty strings.
Either method is okay, the main difference between them is that the first is declarative and functional. It’s a short one-liner that uses a pure function and is focused on the result. But the second method is imperative, as it emphasizes the steps taken to get that result.
Let’s learn how to easily subtract any number of minutes from a Date object in JavaScript.
1. DategetMinutes() and setMinutes() methods
To subtract minutes from a Date:
Call the getMinutes() method on the Date to get the minutes.
Subtract the minutes.
Pass the difference to the setMinutes() method.
For example:
function subtractMinutes(date, minutes) {
date.setMinutes(date.getMinutes() - minutes);
return date;
}
// 2:20 pm on May 18, 2022
const date = new Date('2022-05-18T14:20:00.000Z');
const newDate = subtractMinutes(date, 10);
// 2:10 pm on May 18, 2022
console.log(newDate); // 2022-05-18T14:10:00.000Z
Our subtractMinutes() function takes a Date object and the number of minutes to subtract as arguments. It returns the same Date object with the minutes subtracted.
The DategetMinutes() method returns a number between 0 and 59 that represent the minutes of a particular Date.
The DatesetMinutes() method set the minutes of a Date to a specified number.
If the minutes subtracted decrease the hour, day, month, or year of the Date object, setMinutes() will automatically update the information in the Date to reflect this.
// 10:10 am on March 13, 2022
const date = new Date('2022-03-13T10:10:00.000Z');
date.setMinutes(date.getMinutes() - 30);
// 9:40 am on March 13, 2022
console.log(date); // 2022-05-18T14:10:00.000Z
In this example, decreasing the minutes of the Date by 30 rolls the hour back by 1.
Avoiding side effects
The setMinutes() method mutates the Date object it is called on. This introduces a side effect into our subtractMinutes() function. To avoid modifying the passed Date and create a pure function, make a copy of the Date and call setMinutes() on this copy, instead of the original.
function subtractMinutes(date, minutes) {
// π make copy with "Date" constructor
const dateCopy = new Date(date);
dateCopy.setMinutes(date.getMinutes() - minutes);
return dateCopy;
}
const date = new Date('2022-02-20T11:25:00.000Z');
const newDate = subtractMinutes(date, 5);
// 11:20 am on Feb 20, 2022
console.log(newDate); // 2022-02-20T11:20:00.000Z
// π Original not modified
console.log(date); // 2022-02-20T11:25:00.000Z
Tip:Β Functions that donβt modify external state (i.e., pure functions) tend to be more predictable and easier to reason about, as they always give the same output for a particular input. This makes it a good practice to limit the number of side effects in your code.
2. date-fns subMinutes() function
Alternatively, we can use the subMinutes() function from the date-fns NPM package to quickly subtract minutes from a Date in JavaScript. It works like our pure subtractMinutes() function.
import { subMinutes } from 'date-fns';
const date = new Date('2022-10-03T20:50:00.000Z');
const newDate = subMinutes(date, 25);
// 8:25 pm on October 3, 2022
console.log(newDate); // 2019-02-20T11:20:00.000Z
// Original not modified
console.log(date); // 2022-02-20T11:25:00.000Z
To remove all classes from an element in JavaScript, set the className property of the element to an empty string (''), i.e., element.className = ''. Setting the className property to an empty string will eliminate every class in the element.
const box = document.getElementById('box');
// π Remove all classes from element.
box.className = '';
The className property is used to get and set the value of the class attribute of a specified element.
Setting className to an empty string effectively removes all the classes from the element.
Remove all classes from element with removeAttribute() method
To remove all classes from an element with this approach, call the removeAttribute() method on the specified for the class attribute, i.e., element.removeAttribute('class'). This method will remove the class attribute from the element, effectively removing all the element’s classes.
const box = document.getElementById('box');
// π Remove all classes from element
box.removeAttribute('class');
removeAttribute() takes a name and removes the attribute from an element with that name.
In the first method, the class attribute remains on the element after setting the className property. But using the removeAttribute() method completely removes the class attribute from the element.
If the element doesn’t have a class attribute, removeAttribute() will return without causing an error.
Either of these two methods is fine, it’s up to you which one to pick. I think using the className property is better because it more clearly shows what you’re trying to do.
The “cannot read property ‘0’ of undefined” error occurs when you try to access the 0 index of an array-like variable, but the variable turns out to be undefined. To fix it, initialize the variable to a value of the correct data type before accessing the index.
Depending on your scenario, you might be able to resolve the error by doing one of the following:
Provide a defined fallback value for the variable.
Ensure that the variable has been initialized.
If accessing an index of a nested array, check that none of the outer arrays are undefined.
We’ll be touching on these three solutions in this article.
1. Provide defined fallback value
We can fix the “cannot read property ‘0’ of undefined” error in JavaScript by giving the variable a fallback value before accessing it at a specific index. This solution is beneficial when accessing an array property of an object that might return a value of undefined.
The “cannot read property ‘0’ of undefined” error in JavaScript will occur when you access the 0 index of a variable that is uninitialized. Unintialized variables in JavaScript have a default value of undefined.
let arr;
console.log(arr); // undefined
// β Cannot read properties of undefined (reading '0')
console.log(arr[0]);
const str;
// β Cannot read properties of undefined (reading '0')
console.log(str[0]);
Fixing the error in this case is easy; just set the variable to a value, e.g., an empty array ([]) for arrays, an empty string ('') for strings, etc.
let arr = [];
console.log(arr); // []
// β No error
console.log(arr[0]); // undefined
const str = '';
// β No error
console.log(str[0]); // undefined
3. Check outer arrays for undefined
The “cannot read property ‘0’ of undefined” error can also occur when accessing the 0 index in nested arrays.
For nullish values (undefined or null), the optional chaining operator (?.) returns undefined instead of trying to access the property and causing an error.
Since the 1 index of the outer array returned undefined, the optional chaining operator will prevent the property access.
If the value is not nullish, the ?. operator will perform the property access:
const words = [['javascript']];
console.log(words?.[0]?.[0]); // javascript
console.log(words?.[0]?.[0]?.[0]); // j
The Intersection Observer API is used to asynchronously observe changes in the intersection of an element with the browser’s viewport. It makes it easy to perform tasks that involve detecting the visibility of an element, or the relative visibility of two elements in relation to each other, without making the site sluggish and diminishing the user experience. We’re going to learn all about it in this article.
Uses of Intersection Observer
Before we start exploring the Intersection Observer API, let’s look at some common reasons to use it in our web apps:
Infinite scrolling
This is a web design technique where content is loaded continuously as the user scrolls down. It eliminates the need for pagination and can improve user dwell time.
Lazy loading
Lazy loading is a design pattern in which images or other content are loaded only when they are scrolled into the view of the user, to increase performance and save network resources.
Scroll-based animations
This means animating elements as the user scrolls up or down the page. Sometimes the animation plays completely once a certain scroll position is reached. Other times, the time in the animation changes as the scroll position changes.
Ad revenue calculation
We can use Intersection Observer to detect when an ad is visible to the user and record an impression, which affects ad revenue.
Creating an Intersection Observer
Let’s take a look at a simple use of an Intersection Observer in JavaScript.
The callback function receives an array containing objects of the IntersectionObserverEntry interface. This object contains intersection-related information about an element currently being watched by the Observer.
The callback is called whenever the target element intersects with the viewport. It is also called the first time the Observer is asked to watch the element.
We use the for...of loop to iterate through the entries passed to the callback. We’re observing only one element, so the entries array will contain just the IntersectionObserverEntry element that represents the box, and the for...of loop will have only one iteration.
The isIntersecting property of an IntersectionObserverEntry element returns a boolean value that indicates whether the element is intersecting with the viewport.
When isIntersection is true, it means that the element is transitioning from non-intersecting to intersecting. But when it is false, it indicates that the element is transitioning from intersecting to non-intersecting.
So we use the isIntersection property to set the color of the element to blue as it enters the viewport, and back to black as it leaves.
We call the observe() method on the IntersectionObserver object to make the Observer start watching the element for an intersection.
In the demo below, the white area with the scroll bar represents the viewport. The gray part indicates areas on the page that are outside the viewport and not normally visible in the browser.
Watch how the color of the box changes as soon as one single pixel of it enters the viewport:
Intersection Observer options
Apart from the callback function, the IntersectionObserver() constructor also accepts an options object we use to customize the conditions that must be met for the callback to be invoked.
threshold
The threshold property accepts a value between 0 and 1 that specifies the percentage of the element that must be visible within the viewport for the callback to be invoked. It has a value of 0 by default, meaning that the callback will be run once a single pixel of the element enters the viewport.
Let’s modify our previous example to use a threshold of 1 (100%):
We pass 5 percentage values in an array to the threshold property and display each value as the element reaches it. To do this we use the intersectionRatio property, a number between 0 and 1 indicating the current percentage of the element that is in the viewport.
Notice how the text shown doesn’t always match our thresholds, e.g., 2% was shown for the 0% threshold in the demo. This happens because when we scroll fast and reach a threshold, by the time the callback can fire to update the text, we have already scrolled in more of the element beyond the threshold.
If we scrolled more slowly the callback would have time to update the text before the element scrolls past the current threshold.
rootMargin
The rootMargin property applies a margin around the viewport or root element. It accepts values that the CSS margin property can accept e.g., 10px 20px 30px 40px (top, right, bottom, left). A margin grows or shrinks the region of the viewport that the Intersection Observer watches for an intersection with the target element.
Here’s an example of using the rootMargin property:
index.js
const observer = new IntersectionObserver(
(entries) => {
for (const entry of entries) {
const intersecting = entry.isIntersecting;
entry.target.style.backgroundColor = intersecting ? 'blue' : 'black';
}
},
// π Root margin 50px from bottom of viewport
{ rootMargin: '50px' }
);
const box = document.getElementById('box');
observer.observe(box);
After setting a rootMargin of 50px, the viewport is effectively increased in height for intersection purposes, and the callback function will be invoked when the element comes within 50px of the viewport.
The red lines in the demo indicate the bounds of the region watched by the Observer for any intersection.
We can also specify negative margins to shrink the area of the viewport used for the intersection.
Now the callback is fired when a single pixel of the element is more than 50px inside the viewport.
root
The root property accepts an element that must be an ancestor of the element being observed. By default, it is null, which means the viewport is used. You won’t need to use this property often, but it is handy when you have a scrollable container on your page that you want to check for intersections with one of its child elements.
For instance, to create the demos in this article, I set the root property to a scrollable container on the page, to make it easy for you to visualize the viewport and the areas outside it and gain a better understanding of how the intersection works.
Second callback parameter
The callback passed to the IntersectionObserver() constructor actually has two parameters. The first parameter is the entries parameter we looked at earlier. The second is simply the Observer that is watching for intersections.
This parameter is useful for accessing the Observer from within the callback, especially in situations where the callback is in a location where the Observer variable can’t be accessed, e.g., in a different file from the one containing the Observer variable.
Preventing memory leaks
We need to stop observing elements when they no longer need to be observed, like when they are removed from the DOM or after one-time scroll-based animations, to prevent memory leaks or performance issues.
We can do this with the unobserve() method.
new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
doAnim(entry.target);
observer.unobserve(entry.target);
}
});
});
The unobserver() takes a single element as its argument and stops observing that element.
There is also the disconnect() method, which makes the Observer stop observing all elements.
Conclusion
Intersection Observer is a powerful JavaScript API for easily detecting when an element has intersected with the viewport or a parent element. It lets us implement lazy loading, scroll-based animations, infinite scrolling, and more, without causing performance issues and having to use complicated logic.