Tari Ibaba

Tari Ibaba is a software developer with years of experience building websites and apps. He has written extensively on a wide range of programming topics and has created dozens of apps and open-source libraries.

NEW: *Built-In* Syntax Highlighting on Medium

If you frequently read or write coding articles on Medium you’ll know that it hasn’t had any syntax highlighting support for years now, despite programming being one of the most common topics on the platform. Software writers have had to resort to third-party tools to produce beautiful code highlighting that enhances readability.

Luckily, all that should change soon, as recently the Medium team finally added built-in syntax highlighting support to the code block for major programming languages.

The Medium code block now has syntax highlighting support.
The Medium code block now has syntax highlighting support.

As you can see in the demo, the code block can now automatically detect the code’s language and highlight it.

Manual syntax highlighting

Auto-detection doesn’t always work correctly though, especially for small code snippets, possibly due to the syntax similarities between multiple languages. Notice in the demo how the language detected changed during typing, from R to C++ to Go before arriving at JavaScript.

For tiny code snippets, auto-detection will likely fail:

Auto-detection fails to correctly detect the language.
Bash?

In such a case you can select the correct language from the drop-down list:

Manually setting the language for syntax highlighting.
Manually setting the language for syntax highlighting.

Remove syntax highlighting

If the code is of a language not listed or it doesn’t require highlighting, you can select None and remove the highlighting.

Removing syntax highlighting with the "None" option.
Removing syntax highlighting with the None option.

Note that syntax highlighting isn’t applied to articles published before the feature arrived, probably because it would produce incorrect results in them if auto-detection failed.

So now we no longer need GitHub Gists or Carbon for this. Syntax highlighting on Medium is now easier than ever before.

How to Add Months to a Date in JavaScript

1. Date getMonth() and setMonth() methods

To add months to a Date in JavaScript:

  1. Call the getMonth() to get the number of months.
  2. Add the new months.
  3. Pass the sum to the setMonth() method.

For example:

function addMonths(date, months) {
  date.setMonth(date.getMonth() + months);

  return date;
}

// May 17, 2022
const date = new Date('2022-05-17T00:00:00.000Z');

const newDate = addMonths(date, 4);

// September 17, 2022
console.log(newDate); // 2022-09-17T00:00:00.000Z

Our addMonths() takes a Date object and the number of months to add as arguments. It returns the same Date object with the newly added months.

The Date getMonth() returns a zero-based number that represents the month of a particular date.

The Date setMonth() method sets the months of a date to a specified zero-based number.

Note: “Zero-based” here means that 0 is January, 1 is February, 2 is March, etc.

If the months added would increase the year of the Date, setMonth() will automatically update the information in the Date object to reflect this.

// November 12, 2022
const date = new Date('2022-11-12T00:00:00.000Z');

date.setMonth(date.getMonth() + 3);

// February 12, 2023
console.log(date); // 2023-02-12T00:00:00.000Z

Here we added 3 months to a date in November 2022. This makes setMonth() automatically update the year to 2023.

Avoid side effects

The setMonth() method mutates the Date object it is called on. This introduces a side effect in our addMonths() function. To avoid modifying the passed Date and create a pure function, make a copy of the Date and call setMonth() on this copy, instead of the original.

function addMonths(date, months) {
  // 👇 Make copy with "Date()" constructor
  const dateCopy = new Date(date);

  dateCopy.setMonth(dateCopy.getMonth() + months);

  return dateCopy;
}

// August 16, 2022
const date = new Date('2022-08-16T00:00:00.000Z');

const newDate = addMonths(date, 3);

// November 16, 2022
console.log(newDate); // 2022-11-16T00:00:00.000Z

// 👇 Original not modified
console.log(date); // 2022-08-16T00:00: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 addMonths() function

Alternatively, we can use the addMonths() function from the date-fns library to quickly add months to a Date. It works like our pure addMonths() function.

import { addMonths } from 'date-fns';

// July 14, 2022
const date = new Date('2022-07-14T00:00:00.000Z');

const newDate = addMonths(date, 1);

// August 14, 2022
console.log(newDate); // 2022-08-14T00:00:00.000Z

// Original not modified
console.log(date); // 2022-07-14T00:00:00.000Z

How to Convert CSV to an Array in JavaScript

You can the csvtojson library to quickly convert a CSV file or string to an array of objects in JavaScript:

index.js

import csvToJson from 'csvtojson';

const csvFilePath = 'data.csv';


const array = await csvToJson().fromFile(csvFilePath);

console.log(array);

For a data.csv file like this:

data.csv

color,maxSpeed,age
"red",120,2
"blue",100,3
"green",130,2

This will be the resulting array:

Output

[
  { color: 'red', maxSpeed: '120', age: '2' },
  { color: 'blue', maxSpeed: '100', age: '3' },
  { color: 'green', maxSpeed: '130', age: '2' }
]

Install csvtojson

Before using csvtojson, you’ll need to install it in our project. You can do this with the NPM or Yarn CLI.

npm i csvtojson

# Yarn
yarn add csvtojson

After installation, you’ll be able to import it into a JavaScript module, like this:

import csvToJson from 'csvtojson';

// CommonJS
const csvToJson = require('csvtojson');

Convert CSV file to array with fromFile()

We call the default export function of the csvtojson module to create the object that will convert the CSV to the array. This object has a bunch of methods, each related in some way to the conversion of CSV to a JavaScript object, and fromFile() is one of them.

It accepts the name of the CSV file to convert, and returns a Promise, as the conversion is an asynchronous process. The Promise will resolve with the resulting JSON string.

Convert CSV string to array with fromString()

To convert from a CSV data string directly, instead of a file, you can use the also asynchronous fromString() method of the converter object instead:

index.js

import csvToJson from 'csvtojson';

const csv = `"First Name","Last Name","Age"
"Russell","Castillo",23
"Christy","Harper",35
"Eleanor","Mark",26`;

const array = await csvToJson().fromString(csv);

console.log(array);

Output

[
  { 'First Name': 'Russell', 'Last Name': 'Castillo', Age: '23' },
  { 'First Name': 'Christy', 'Last Name': 'Harper', Age: '35' },
  { 'First Name': 'Eleanor', 'Last Name': 'Mark', Age: '26' }
]

Customize conversion of CSV to array

The default export function of csvtojson accepts an object used to specify options to customize the conversion process.

One such option is header, an array used to specify the headers in the CSV data.

index.js

import csvToJson from 'csvtojson';

const csv = `"First Name","Last Name","Age"
"Russell","Castillo",23
"Christy","Harper",35
"Eleanor","Mark",26`;

const array = await csvToJson({
  headers: ['firstName', 'lastName', 'age'],
}).fromString(csv);

console.log(array);

Output

[
  { firstName: 'Russell', lastName: 'Castillo', age: '23' },
  { firstName: 'Christy', lastName: 'Harper', age: '35' },
  { firstName: 'Eleanor', lastName: 'Mark', age: '26' }
]

Another is delimeter, used to indicate the character that separates the columns:

import csvToJson from 'csvtojson';

const csv = `"First Name"|"Last Name"|"Age"
"Russell"|"Castillo"|23
"Christy"|"Harper"|35
"Eleanor"|"Mark"|26`;

const array = await csvToJson({
  headers: ['firstName', 'lastName', 'age'],
  delimiter: '|',
}).fromString(csv);

Output

[
  { firstName: 'Russell', lastName: 'Castillo', age: '23' },
  { firstName: 'Christy', lastName: 'Harper', age: '35' },
  { firstName: 'Eleanor', lastName: 'Mark', age: '26' }
]

We also have ignoreColumns, an option that instructs the converter to ignore certain columns, using a regular expression.

import csvToJson from 'csvtojson';

const csv = `"First Name"|"Last Name"|"Age"
"Russell"|"Castillo"|23
"Christy"|"Harper"|35
"Eleanor"|"Mark"|26`;

const array = await csvToJson({
  headers: ['firstName', 'lastName', 'age'],
  delimiter: '|',
  ignoreColumns: /lastName/,
}).fromString(csv);

console.log(array);

Output

[
  { firstName: 'Russell', age: '23' },
  { firstName: 'Christy', age: '35' },
  { firstName: 'Eleanor', age: '26' }
]

Convert CSV to array of rows

By setting the output option to 'csv', we can produce a list of arrays, where each array represents a row, containing the value of all columns of that row.

For example:

index.js

import csvToJson from 'csvtojson';

const csv = `color,maxSpeed,age
"red",120,2
"blue",100,3
"green",130,2`;

const array = await csvToJson({
  output: 'csv',
}).fromString(csv);

console.log(array);

Output

[
  [ 'red', '120', '2' ],
  [ 'blue', '100', '3' ],
  [ 'green', '130', '2' ]
]

Native conversion of CSV to array

It’s also possible to convert CSV to a JavaScript array without using any third-party libraries.

index.js

function csvToArray(csv) {
  // \n or \r\n depending on the EOL sequence
  const lines = csv.split('\n');
  const delimeter = ',';

  const result = [];

  const headers = lines[0].split(delimeter);

  for (const line of lines) {
    const obj = {};
    const row = line.split(delimeter);

    for (let i = 0; i < headers.length; i++) {
      const header = headers[i];
      obj[header] = row[i];
    }

    result.push(obj);
  }

  // Prettify output
  return JSON.stringify(result, null, 2);
}

const csv = `color,maxSpeed,age
"red",120,2
"blue",100,3
"green",130,2`;

const array = csvToArray(csv);

console.log(array);

Output

[
  {
    "color": "color",
    "maxSpeed": "maxSpeed",
    "age": "age"
  },
  {
    "color": "\"red\"",
    "maxSpeed": "120",
    "age": "2"
  },
  {
    "color": "\"blue\"",
    "maxSpeed": "100",
    "age": "3"
  },
  {
    "color": "\"green\"",
    "maxSpeed": "130",
    "age": "2"
  }
]

You can modify the code above to allow for varying and more complex CSV data.

How to Convert CSV to JSON in JavaScript

You can use the csvtojson library to quickly convert CSV to JSON in JavaScript:

index.js

index.js
import csvToJson from 'csvtojson'; const csvFilePath = 'data.csv'; const json = await csvToJson().fromFile(csvFilePath); const jsonString = JSON.stringify(json, null, 2) console.log(jsonString);

For a data.csv file like this:

data.csv
color,maxSpeed,age "red",120,2 "blue",100,3 "green",130,2

This will be the resulting JSON:

JSON
[ { "color": "red", "maxSpeed": "120", "age": "2" }, { "color": "blue", "maxSpeed": "100", "age": "3" }, { "color": "green", "maxSpeed": "130", "age": "2" } ]

We use csvtojson to convert the CSV into a JSON object, and use the JSON.stringify() method to convert the object into a well-formatted JSON string.

Install csvtojson

Before using csvtojson, you’ll need to install it in our project. You can do this with the NPM or Yarn CLI.

Shell
npm i csvtojson # Yarn yarn add csvtojson

After installation, you’ll be able to import it into a JavaScript module, like this:

JavaScript
import csvToJson from 'csvtojson'; // CommonJS const csvToJson = require('csvtojson');

Convert CSV file to JSON with fromFile()

We call the default export function of the csvtojson module to create the object that will convert the CSV. This object has a bunch of methods, each related in some way to the conversion of CSV to JSON, and fromFile() is one of them.

It accepts the name of the CSV file to convert, and returns a Promise, as the conversion is an asynchronous process. The Promise will resolve with the resulting JSON string.

Convert CSV string to JSON with fromString()

To convert from a CSV data string directly, instead of a file, you can use the also asynchronous fromString() method of the converter object instead:

index.js
import csvToJson from 'csvtojson'; const csv = `"First Name","Last Name","Age" "Russell","Castillo",23 "Christy","Harper",35 "Eleanor","Mark",26`; const json = await csvToJson().fromString(csv); const jsonString = JSON.stringify(json, null, 2); console.log(jsonString); 
JSON
[ { "First Name": "Russell", "Last Name": "Castillo", "Age": "23" }, { "First Name": "Christy", "Last Name": "Harper", "Age": "35" }, { "First Name": "Eleanor", "Last Name": "Mark", "Age": "26" } ]

Customize conversion of CSV to JSON

The default export function of csvtojson accepts an object used to specify options to customize the conversion process.

One such option is header, an array used to specify the headers in the CSV data.

index.js
import csvToJson from 'csvtojson'; const csv = `"First Name","Last Name","Age" "Russell","Castillo",23 "Christy","Harper",35 "Eleanor","Mark",26`; const json = await csvToJson({ headers: ['firstName', 'lastName', 'age'], }).fromString(csv); console.log(json);
JSON
[ { "firstName": "Russell", "lastName": "Castillo", "age": "23" }, { "firstName": "Christy", "lastName": "Harper", "age": "35" }, { "firstName": "Eleanor", "lastName": "Mark", "age": "26" } ]

Another is delimeter, used to indicate the character that separates the columns:

index.js
import csvToJson from 'csvtojson'; const csv = `"First Name"|"Last Name"|"Age" "Russell"|"Castillo"|23 "Christy"|"Harper"|35 "Eleanor"|"Mark"|26`; const json = await csvToJson({ headers: ['firstName', 'lastName', 'age'], delimiter: '|', }).fromString(csv); const jsonString = JSON.stringify(json, null, 2); console.log(jsonString);
JSON
[ { "firstName": "Russell", "lastName": "Castillo", "age": "23" }, { "firstName": "Christy", "lastName": "Harper", "age": "35" }, { "firstName": "Eleanor", "lastName": "Mark", "age": "26" } ]

We also have ignoreColumns, an option that instructs the converter to ignore certain columns, using a regular expression.

index.js
import csvToJson from 'csvtojson'; const csv = `"First Name"|"Last Name"|"Age" "Russell"|"Castillo"|23 "Christy"|"Harper"|35 "Eleanor"|"Mark"|26`; const json = await csvToJson({ headers: ['firstName', 'lastName', 'age'], delimiter: '|', ignoreColumns: /lastName/, }).fromString(csv); const jsonString = JSON.stringify(json, null, 2); console.log(jsonString);
JSON
[ { "firstName": "Russell", "age": "23" }, { "firstName": "Christy", "age": "35" }, { "firstName": "Eleanor", "age": "26" } ]

Convert CSV to JSON array of rows

By setting the output option to 'csv', we can produce a list of arrays, where each array represents a row, containing the value of all columns of that row.

For example:

index.js
import csvToJson from 'csvtojson'; const csv = `color,maxSpeed,age "red",120,2 "blue",100,3 "green",130,2`; const json = await csvToJson({ output: 'csv', }).fromString(csv); const jsonString = JSON.stringify(json, null, 2); console.log(jsonString);
JSON
[ [ "red", "120", "2" ], [ "blue", "100", "3" ], [ "green", "130", "2" ] ]

Native conversion of CSV to JSON

It’s also possible to convert CSV to JSON without using any third-party libraries.

index.js
function csvToJson(csv) { // \n or \r\n depending on the EOL sequence const lines = csv.split('\n'); const delimeter = ','; const result = []; const headers = lines[0].split(delimeter); for (const line of lines) { const obj = {}; const row = line.split(delimeter); for (let i = 0; i < headers.length; i++) { const header = headers[i]; obj[header] = row[i]; } result.push(obj); } // Prettify output return result; } const csv = `color,maxSpeed,age red,120,2 blue,100,3 green,130,2`; const json = csvToJson(csv); const jsonString = JSON.stringify(json, null, 2); console.log(jsonString);

You can modify the code above to allow for varying and more complex CSV data.

Output:

JSON
[ { "color": "color", "maxSpeed": "maxSpeed", "age": "age" }, { "color": "red", "maxSpeed": "120", "age": "2" }, { "color": "blue", "maxSpeed": "100", "age": "3" }, { "color": "green", "maxSpeed": "130", "age": "2" } ]

How to Open a Link in a New Tab Programmatically in React

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://wp.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://wp.codingbeautydev.com', '_blank', 'noreferrer');
    }
  }, [timeLeft]);

  return (
    <div>
      The link will open in <b>{timeLeft}</b> second(s)
    </div>
  );
}
The link is opened in a new tab when the countdown ends.
The link is opened in a new tab when the countdown ends.

We use the open() method of the window object to programmatically open a link in a new tab. This method has three optional parameters:

  1. url: The URL of the page to open in a new tab.
  2. 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.
  3. 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.

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 wp.codingbeautydev.com in a new tab</p>

      <button
        role="link"
        onClick={() => openInNewTab('https://wp.codingbeautydev.com')}
      >
        Visit
      </button>
    </div>
  );
}
Clicking the button opens the link in a new tab.
Clicking the button opens the link in a new tab.

How to Quickly Open a Link in a New Tab in React

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://wp.codingbeautydev.com" target="_blank">Link</a>. The _blank value specifies that the link should be opened in a new tab.

For example:

App.js

export default function App() {
  return (
    <div id="app">
      <a href="https://wp.codingbeautydev.com" target="_blank" rel="noreferrer">
        Coding Beauty
      </a>

      <br />
      <br />

      <a
        href="https://wp.codingbeautydev.com/blog"
        target="_blank"
        rel="noreferrer"
      >
        Coding Beauty Blog
      </a>
    </div>
  );
}

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.

Clicking the link opens the URL in a new tab.
Clicking the link opens it in a new tab.

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://wp.codingbeautydev.com', '_blank', 'noreferrer');
    }
  }, [timeLeft]);

  return (
    <div>
      The link will open in <b>{timeLeft}</b> second(s)
    </div>
  );
}
The link is opened in a new tab when the countdown ends.
The link is opened in a new tab when the countdown ends.

We use the open() method of the window object to programmatically open a link in a new tab. This method has three optional parameters:

  1. url: The URL of the page to open in a new tab.
  2. 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.
  3. 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.

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 wp.codingbeautydev.com in a new tab</p>

      <button
        role="link"
        onClick={() => openInNewTab('https://wp.codingbeautydev.com')}
      >
        Visit
      </button>
    </div>
  );
}
Clicking the button opens the link in a new tab.
Clicking the button opens the link in a new tab.

How to Check if a String Contains Uppercase Letters in JavaScript

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.

For example:

function containsUppercase(str) {
  return /[A-Z]/.test(str);
}

console.log(containsUppercase('javascript')); // false
console.log(containsUppercase('PHP')); // true
console.log(containsUppercase('Coding')); // true

The RegExp test() 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]+$/.

function containsUppercase(str) {
  return /^[A-Z]+$/.test(str);
}

console.log(containsUppercase('javascript')); // false
console.log(containsUppercase('PHP')); // true
console.log(containsUppercase('Coding')); // false

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.

String match() method

An alternative to RegExp test() is the String match() method. Instead of calling test() on the regex, we call match() on the string with the regex as an argument.

function containsUppercase(str) {
  return Boolean(str.match(/[A-Z]/));
}

console.log(containsUppercase('javascript')); // false
console.log(containsUppercase('PHP')); // true
console.log(containsUppercase('Coding')); // true

The String match() method returns an array of all the matches of a regular expression in a string. If there are no matches, it returns null.

const str1 = 'javascript';
const str2 = 'Beauty';

console.log(str1?.match(/[A-Z]/)); // null
console.log(str2?.match(/[A-Z]/)); // [ 'B', ... ] (single-item array)

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: undefinednullNaN0'' (empty string), and false. Every other value is truthy.

console.log(Boolean(undefined)); // false
console.log(Boolean(['letters'])); // true
console.log(Boolean(null)); // false
console.log(Boolean(5)); // true

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.

const str = null;

console.log(str?.match(/[A-Z]/)); // undefined

How to Split a String Every N Characters in JavaScript

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.

For example:

const str = 'codingbeauty';

const result = str.match(/.{1,4}/g) ?? [];

console.log(result); // [ 'codi', 'ngbe', 'auty' ];

The String match() 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.

const str = '';

const result = str.match(/.{1,4}/g) || [];

console.log(result); // []

The ?? operator returns the value to its left if it is null or undefined. Otherwise, it returns the value to its right.

console.log(null ?? 5); // 5

console.log(2 ?? 5); // 2

console.log(undefined ?? 10); // 10

console.log('' ?? 10); // '' (empty string)

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 String substring() 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:

const splitString = (str, N) =>
  [...str]
    .reduce(
      (substrings, ch) =>
        (substrings.at(-1)?.length ?? N) < N
          ? [...substrings.slice(0, -1), substrings.at(-1) + ch]
          : [...substrings, ch],
      []
    );

// [ 'codi', 'ngbe', 'auty' ]
console.log(splitString('codingbeauty', 4));

// [ 'codi', 'ngbe', 'auty', 'dev' ]
console.log(splitString('codingbeautydev', 4));

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.

How Does the useDeferredValue Hook Work in React?

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.

Let’s say we have the following code:

App.js

export default function App() {
  const [name, setName] = useState('');

  const computedValue = useMemo(() => {
    return getComputedValue(name);
  }, [name]);

  const handleChange = (event) => {
    setName(event.target.value);
  };

  return (
    <input
      type="text"
      placeholder="Username"
      value={name}
      onChange={handleChange}
    />
  );
}

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:

App.js

function App() {
  const [query, setQuery] = useState('');

  const list = useMemo(() => {
    // 👇 Filtering through large list impacts performance
    return largeList.filter((item) => item.name.includes(query));
  }, [query]);

  const handleChange = (event) => {
    setQuery(event.target.value);
  };

  return (
    <>
      <input type="text" value={query} onChange={handleChange} placeholder="Search"/>
      {list.map((item) => (
        <SearchResultItem key={item.id} item={item} />
      ))}
    </>
  );
}

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.

The input doesn't respond to keystrokes fast enough.
The input doesn’t respond to keystrokes fast enough.

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.

function App() {
  const [query, setQuery] = useState('');

  // 👇 useDefferedValue
  const deferredQuery = useDefferedValue(query);

  const list = useMemo(() => {
    return largeList.filter((item) => item.name.includes(query));
  }, [deferredQuery]);

  const handleChange = (event) => {
    setQuery(event.target.value);
  };

  return (
    <>
      <input type="text" value={query} onChange={handleChange} placeholder="Search" />
      {list.map((item) => (
        <SearchResultItem key={item.id} item={item} />
      ))}
    </>
  );
}

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, then deferredQuery 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.

The input responds instantly to keystrokes.
The input field responds instantly to keystrokes.

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:

Typing quickly prevents the list from updating right away.
Typing quickly prevents the list from updating right away.

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.

How to Remove Empty Strings From an Array in JavaScript

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.

For example:

const arr = ['c', '', 'o', '', '', 'd', '', 'e'];

const noEmptyStrings = arr.filter((str) => str !== '');

console.log(noEmptyStrings); // [ 'c', 'o', 'd', 'e' ]

The Array filter() method creates a new array filled with elements that pass a test specified by a callback function. It doesn’t modify the original array.

const arr = [1, 2, 3, 4];

const filtered = arr.filter((num) => num > 2);
console.log(filtered); // [ 3, 4 ]

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.

const arr = ['c', '', 'o', '', '', 'd', '', 'e'];

const noEmptyStrings = [];

for (const item of arr) {
  if (item !== '') {
    noEmptyStrings.push(item);
  }
}

console.log(noEmptyStrings); // [ 'c', 'o', 'd', 'e' ]

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.