tutorial

How to Get the Mouse Position in React

To get the position of the mouse in React, add a mousemove event handler to the window object and access the clientX and clientY properties of the MouseEvent object to get the X and Y coordinates of the mouse respectively.

For example:

App.js

import { useEffect, useState } from 'react';

export default function App() {
  const [mousePos, setMousePos] = useState({});

  useEffect(() => {
    const handleMouseMove = (event) => {
      setMousePos({ x: event.clientX, y: event.clientY });
    };

    window.addEventListener('mousemove', handleMouseMove);

    return () => {
      window.removeEventListener(
        'mousemove',
        handleMouseMove
      );
    };
  }, []);

  return (
    <div>
      The mouse is at position{' '}
      <b>
        ({mousePos.x}, {mousePos.y})
      </b>
    </div>
  );
}
The current mouse position is displayed.
The current mouse position is displayed.

The mousemove event is triggered on an element when the mouse hovers on it. To be more precise, it is fired when the mouse is moved and the hotspot of the cursor is within the bounds of the element.

We attach the event listener to the window object to trigger the event whenever the mouse is moved anywhere in the page.

We passed an empty dependencies array to the useEffect hook because we want to add a handler for the mousemove event only once – when the component mounts.

In the cleanup function, we use the removeEventListener() method to remove the event listener previously added and prevent a memory leak when the component is unmounted.

The mousemove event listener receives a MouseEvent object used to access information and perform actions related to the event. We use the clientX and clientY properties of this object to get the position of the mouse on the X-coordinate and Y-coordinate respectively in the viewport of the application.

Get mouse position relative to element in React

In the previous example we were able to get the mouse position in global coordinates.

In global coordinates position (0,0) is at the top left of the webpage and position (Xmax, Ymax) is at the bottom right.

We might instead want to get the mouse position within the region of an element.

To get the mouse position relative to an element in React, set an onMouseMove event handler on the element, then calculate the local X and Y position using properties of the MouseEvent object passed to the event handler.

For example:

App.js

import { useEffect } from 'react';
import { useState } from 'react';

export default function App() {
  const [globalMousePos, setGlobalMousePos] = useState({});
  const [localMousePos, setLocalMousePos] = useState({});

  const handleMouseMove = (event) => {
    // 👇 Get mouse position relative to element
    const localX = event.clientX - event.target.offsetLeft;
    const localY = event.clientY - event.target.offsetTop;

    setLocalMousePos({ x: localX, y: localY });
  };

  useEffect(() => {
    const handleMouseMove = (event) => {
      setGlobalMousePos({
        x: event.clientX,
        y: event.clientY,
      });
    };

    window.addEventListener('mousemove', handleMouseMove);

    return () => {
      window.removeEventListener(
        'mousemove',
        handleMouseMove
      );
    };
  }, []);

  return (
    <div>
      <div
        style={{
          border: '1px solid gray',
          display: 'inline-block',
          padding: '75px',
          textAlign: 'center',
        }}
        onMouseMove={handleMouseMove}
      >
        Local
        <br />
        <b>
          ({localMousePos.x}, {localMousePos.y})
        </b>
      </div>
      <br />
      Global
      <br />
      <b>
        ({globalMousePos.x}, {globalMousePos.y})
      </b>
    </div>
  );
}

Now the resulting X and Y coordinates will be relative to the element. For example, position (0,0) will be at the top left of the element, not the page:

The mouse position relative to the element is shown.
The mouse position relative to the element is shown.

We subtract the offsetLeft property of the element from the clientX property of the MouseEvent object to get the X position relative to the element.

Similarly, to get the Y position, we subtract the offsetTop property of the element from the clientY property of the MouseEvent object.

const handleMouseMove = (event) => {
  // Calculate position within bounds of element
  const localX = event.clientX - event.target.offsetLeft;
  const localY = event.clientY - event.target.offsetTop;

  setLocalMousePos({ x: localX, y: localY });
};

The offsetLeft property returns the number of pixels between the left position of an element and that of its parent.

Likewise, the offsetTop property returns the number of pixels between the top position of an element and that of its parent.

How to Convert JSON to XML in Node.js

We can use the xml-js library to easily convert a JSON string to an XML string in Node.js.

import { json2xml } from 'xml-js';

const jsonObj = {
  name: 'Garage',
  cars: [
    { color: 'red', maxSpeed: 120, age: 2 },
    { color: 'blue', maxSpeed: 100, age: 3 },
    { color: 'green', maxSpeed: 130, age: 2 },
  ],
};

const json = JSON.stringify(jsonObj);

const xml = json2xml(json, { compact: true, spaces: 4 });

console.log(xml);

This code will have the following output:

<name>Garage</name>
<cars>
    <color>red</color>
    <maxSpeed>120</maxSpeed>
    <age>2</age>
</cars>
<cars>
    <color>blue</color>
    <maxSpeed>100</maxSpeed>
    <age>3</age>
</cars>
<cars>
    <color>green</color>
    <maxSpeed>130</maxSpeed>
    <age>2</age>
</cars>

Install xml-js

Before using xml-js, we’ll need to install it in our project. We can do this with the NPM CLI.

npm i xml-js

Or with the Yarn CLI:

yarn add xml-js

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

import { json2xml } from 'xml-js';

We use import destructuring to access the json2xml() method directly from the library.

For a CommonJS module, we’ll import it like this instead:

const { json2xml } = require('xml-js');

The json2xml() function

The json2xml() function from the library has two parameters. The first is the JSON string to convert to XML, and the second is an object.

const xml = json2xml(json, { compact: true, spaces: 4 });

Customize conversion of JSON to XML in Node.js

This object is used to specify various options for customizing the conversion process.

In our example, we set the compact property to true to indicate that the JSON string input is in a compact form.

We set the spaces property to 4 to indent nested XML nodes by 4 spaces. So we can reduce the indentation by setting spaces to 1:

import { json2xml } from 'xml-js';

const jsonObj = {
  name: 'Garage',
  cars: [
    { color: 'red', maxSpeed: 120, age: 2 },
    { color: 'blue', maxSpeed: 100, age: 3 },
    { color: 'green', maxSpeed: 130, age: 2 },
  ],
};

const json = JSON.stringify(jsonObj);

const xml = json2xml(json, { compact: true, spaces: 1 });

console.log(xml);

Now we will have the following XML output:

<name>Garage</name>
<cars>
 <color>red</color>
 <maxSpeed>120</maxSpeed>
 <age>2</age>
</cars>
<cars>
 <color>blue</color>
 <maxSpeed>100</maxSpeed>
 <age>3</age>
</cars>
<cars>
 <color>green</color>
 <maxSpeed>130</maxSpeed>
 <age>2</age>
</cars>

Native conversion of JSON to XML in Node.js

If you don’t want to use any third-party libraries, then you can use this recursive function to convert JSON to XML in Node.js.

function JSONtoXML(obj) {
  let xml = '';
  for (let prop in obj) {
    xml += obj[prop] instanceof Array ? '' : '<' + prop + '>';
    if (obj[prop] instanceof Array) {
      for (let array in obj[prop]) {
        xml += '\n<' + prop + '>\n';
        xml += JSONtoXML(new Object(obj[prop][array]));
        xml += '</' + prop + '>';
      }
    } else if (typeof obj[prop] == 'object') {
      xml += JSONtoXML(new Object(obj[prop]));
    } else {
      xml += obj[prop];
    }
    xml += obj[prop] instanceof Array ? '' : '</' + prop + '>\n';
  }
  xml = xml.replace(/<\/?[0-9]{1,}>/g, '');
  return xml;
}

const jsonObj = {
  name: 'Garage',
  cars: [
    { color: 'red', maxSpeed: 120, age: 2 },
    { color: 'blue', maxSpeed: 100, age: 3 },
    { color: 'green', maxSpeed: 130, age: 2 },
  ],
};

const xml = JSONtoXML(jsonObj);

console.log(xml);

This code will produce the following output:

<name>Garage</name>

<cars>
<color>red</color>
<maxSpeed>120</maxSpeed>
<age>2</age>
</cars>
<cars>
<color>blue</color>
<maxSpeed>100</maxSpeed>
<age>3</age>
</cars>
<cars>
<color>green</color>
<maxSpeed>130</maxSpeed>
<age>2</age>
</cars>

How to Change the Style of an Element on Click in Vue

To change the style of an element on click in Vue:

  1. Create a boolean state variable to conditionally set the style on the element depending on the value of this variable.
  2. Set a click event handler on the element that toggles the value of the state variable.

For example:

App.vue

<template>
  <div id="app">
    <p>Click the button to change its color.</p>

    <button
      role="link"
      @click="handleClick"
      class="btn"
      :style="{
        backgroundColor: active ? 'white' : 'blue',
        color: active ? 'black' : 'white',
      }"
    >
      Click
    </button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      active: false,
    };
  },
  methods: {
    handleClick() {
      this.active = !this.active;
    },
  },
};
</script>

<style>
.btn {
  border: 1px solid gray;
  padding: 8px 16px;
  border-radius: 5px;
  font-family: 'Segoe UI';
  font-weight: bold;
}
</style>
Clicking the element changes its stye.
Clicking the element changes its style.

The active state variable determines the style that will be applied to the element. When it is false (the default), a certain style is applied.

We set a click event handler on the element, so that the handler will get called when it is clicked. The first time this handler is called, the active variable gets toggled to true, which changes the style of the element.

Note

To prevent the style from changing every time the element is clicked, we can set the state variable to true, instead of toggling it:

handleClick() {
  this.active = true

  // this.active = !this.active
},

We used ternary operators to conditionally set the backgroundColor and color style on the element.

The ternary operator works like an if/else statement. It returns the value before the ? if it is truthy. Otherwise, it returns the value to the left of the :.

const treshold = 10;

const num = 11;

const result = num > treshold ? 'Greater' : 'Lesser';

console.log(result) // Greater

So if the active variable is true, the backgroundColor and color are set to white and black respectively. Otherwise, they’re set to blue and white respectively.

Change element style on click with classes

To change the style of an element on click in Vue, we can also create classes containing the alternate styles and conditionally set them to the class prop of the element, depending on the value of the boolean state variable.

For example:

App.vue

<template>
  <div id="app">
    <p>Click the button to change its color.</p>

    <button
      role="link"
      @click="handleClick"
      class="btn"
      :class="active ? 'active' : 'non-active'"
    >
      Click
    </button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      active: false,
    };
  },
  methods: {
    handleClick() {
      this.active = !this.active;
    },
  },
};
</script>

<style>
.btn {
  border: 1px solid gray;
  padding: 8px 16px;
  border-radius: 5px;
  font-family: 'Segoe UI';
  font-weight: bold;
}

.active {
  background-color: white;
  color: black;
}

.non-active {
  background-color: blue;
  color: white;
}
</style>

We create two classes (active and non-active) with different styles, then we use the ternary operator to add the active class if the active variable is true, and add the non-active class if otherwise.

The advantage of using classes is that we get to cleanly separate the styles from the template markup. Also, we only need to use one ternary operator.

Change element style on click with event.currentTarget.classList

There are other ways to change the style of an element in Vue without using a state variable.

With classes defined, we can use the currentTarget.classList property of the Event object passed to the click event handler to change the style of the element.

For example:

App.vue

<template>
  <div id="app">
    <p>Click the button to change its color.</p>

    <button
      role="link"
      @click="handleClick"
      class="btn non-active"
    >
      Click
    </button>
  </div>
</template>

<script>
export default {

  methods: {
    handleClick(event) {
      // 👇 Change style
      event.currentTarget.classList.remove('non-active');
      event.currentTarget.classList.add('active');
    },
  },
};
</script>

<style>
.btn {
  border: 1px solid gray;
  padding: 8px 16px;
  font-family: Arial;
  font-size: 1.1em;
  box-shadow: 0 2px 5px #c0c0c0;
}

.active {
  background-color: white;
  color: black;
}

.non-active {
  background-color: rebeccapurple;
  color: white;
}
</style>
Clicking the element changes its style.
Clicking the element changes its style.

We don’t use a state variable this time, so we add the non-active class to the element, to customize its default appearance.

The click event listener receives an Event object used to access information and perform actions related to the click event.

The currentTarget property of this object returns the element that was clicked and had the event listener attached.

We call the classList.remove() method on the element to remove the non-active class, then we call the classList.add() method on it to add the active class.

Notice that the style of the element didn’t change anymore after being clicked once. If you want to toggle the style whenever it is clicked, you can use the toggle() class of the element to alternate the classes on the element.

App.vue

<template>
  <div id="app">
    <p>Click the button to change its color.</p>

    <button
      role="link"
      @click="handleClick"
      class="btn non-active"
    >
      Click
    </button>
  </div>
</template>

<script>
export default {
  methods: {
    handleClick(event) {

      // 👇 Alternate classes
      event.currentTarget.classList.toggle('non-active');
      event.currentTarget.classList.toggle('active');
    },
  },
};
</script>

<style>
.btn {
  border: 1px solid gray;
  padding: 8px 16px;
  font-family: Arial;
  font-size: 1.1em;
  box-shadow: 0 2px 5px #c0c0c0;
}

.active {
  background-color: white;
  color: black;
}

.non-active {
  background-color: rebeccapurple;
  color: white;
}
</style>
Clicking the element toggles its color.
Clicking the element toggles its color.

The classList.toggle() method removes a class from an element if it is present. Otherwise, it adds the class to the element.

How to Fix the “Cannot read property ‘addEventListener’ of null” Error in JavaScript

The “cannot read property ‘addEventListener’ of null” error occurs in JavaScript when you try to call the addEventListener() method on an element that cannot be found in the DOM. This happens for two main reasons:

  1. Accessing the addEventListener() method on an element absent from the DOM.
  2. Inserting the script tag referencing the JavaScript file at a point above the declaration of the DOM element in the HTML.

We’ll learn how to handle the error for these two scenarios in this article.

The "cannot read property 'addEventListener' of null" error occurring in JavaScript.

Cause 1: Accessing addEventListener() on an element not present in the DOM

index.js

const btn = document.getElementById('does-not-exist');

console.log(btn); // null

// ❌ Cannot read property 'addEventListener' of null
btn.addEventListener('click', () => {
  alert('You clicked the button');
});

When a method like getElementById() or querySelector() method is used to search for an element that doesn’t exist in the DOM, it returns null. And attempting to call the addEventListener() method on a null value will cause the error.

Solve: Ensure correct selector

To fix the “cannot read property ‘addEventListener’ of null” error, make sure the selector used the access the element is properly defined. Ensure that there are no mistakes in the ID or class name, and the correct symbols are used.

Solve: Check for null

To fix the “cannot read property ‘addEventListener’ of null” error, check that the element is not null before calling the addEventListener() method on it.

We can do this with an if statement:

const btn = document.getElementById('does-not-exist');

console.log(btn); // null

// âś… Check if element exists before calling addEventListener()
if (btn) {
  // Not called
  btn.addEventListener('click', () => {
    alert('You clicked the button');
  });
}

When a value is placed in between the brackets of an if statement, it is coerced to a Boolean before being evaluated, i.e., truthy values become true, and falsy values become false. null is a falsy value, so it is coerced to false and the code in the if statement block is never run.

Note: In JavaScript, there are six falsy values: undefined, null, NaN, 0, '' (empty string) and false. Every other value is truthy.

We can also use the optional chaining operator (?.) to check if the element is null.

const btn = document.getElementById('does-not-exist');

console.log(btn); // null

// âś… Check if element exists before calling addEventListener()

// Not called
btn?.addEventListener('click', () => {
  alert('You clicked the button');
});

The optional chaining operator (?.) is null-safe way of accessing a property or calling a method of an object. If the object is nullish (null or undefined), the operator prevents the member access and returns undefined instead of throwing an error.

Cause 2: Inserting the script tag above the DOM element

Another common cause of this error is placing the <script> tag referencing the JavaScript file at a point above where the target element is declared.

For example, in this HTML markup:

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Coding Beauty Tutorial</title>
    <!-- ❌ Script is run before button is declared -->
    <script src="index.js"></script>
  </head>
  <body>
    <button id="btn">Sign up</button>
  </body>
</html>

the script tag is placed in the head tag, above where the button element is declared, so the index.js file will not be able to access the button element.

index.js

const btn = document.getElementById('btn');

console.log(btn); // null

// ❌ TypeError: Cannot read properties of null
btn.addEventListener('click', () => {
  alert('You clicked the button');
});

Solve: Move script tag to bottom of body

To fix the error in this case, move the script tag to the bottom of the body, after all the HTML elements have been declared.

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Coding Beauty Tutorial</title>
  </head>
  <body>
    <button id="btn">Sign up</button>

    <!-- âś… Script is run after button is declared -->
    <script src="index.js"></script>
  </body>
</html>

Now the index.js script file will have access to the button element and all the other HTML elements, because they would have already been declared when the script is run.

index.js

const btn = document.getElementById('btn');

console.log(btn); // HTMLButtonElement object

// âś… Works as expected
btn.addEventListener('click', () => {
  alert('You clicked the button');
});

Solve: Access element in DOMContentLoaded event listener

Another way to fix the “cannot read property ‘addEventListener’ of null” error in JavaScript is to add a DOMContentLoaded event listener to the document, and access the element in this listener. With this approach it won’t matter where we place the script in the HTML.

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Coding Beauty Tutorial</title>

    <!-- Script placed above element accessed -->
    <script src="index.js"></script>
  </head>
  <body>
    <button id="btn">Sign up</button>
  </body>
</html>

The DOMContentLoaded event is fired when the browser has fully loaded the HTML, and the DOM tree has been built, but external resources like images and stylesheets may not have loaded. So regardless of where we place the script, the code in the listener is only called after all the declared HTML elements have been added to the DOM.

index.js

document.addEventListener('DOMContentLoaded', () => {
  const btn = document.getElementById('btn');

  console.log(btn); // HTMLButtonElement object

  // âś… Works as expected
  btn.addEventListener('click', () => {
    alert('You clicked the button');
  });
});

Conclusion

We can fix the “cannot read property addEventListener’ of null” error in JavaScript by ensuring that the correct selector is defined, adding a null check to the element before calling addEventListener(), moving the script tag to the bottom of the body, or accessing the element in a DOMContentLoaded event listener added to the document.

How to Open a Link in a New Tab in Vue

To open a link in a new tab in Vue, create an anchor (<a>) element and set its target attribute to _blank, e.g., <a href="https://codingbeautydev.com" target="_blank"></a>. The _blank value specifies that the link should be opened in a new tab.

App.vue

<template>
  <div id="app">
    <a
      href="https://codingbeautydev.com"
      target="_blank"
      rel="noreferrer"
    >
      Coding Beauty
    </a>

    <br /><br />

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

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.

The link is opened in a new tab.
The link is opened in a new tab.

Sometimes we’ll prefer a button instead of a link to open the new tab when clicked.

To open a link in a new tab on button click, create a button element and set an click event listener that calls the window.open() method.

App.vue

<template>
  <div id="app">
    <p>
      Click this button to visit Coding Beauty in a new tab
    </p>

    <button
      role="link"
      @click="openInNewTab('https://codingbeautydev.com')"
    >
      Click
    </button>
  </div>
</template>

<script>
export default {
  methods: {
    openInNewTab(url) {
      window.open(url, '_blank', 'noreferrer');
    },
  },
};
</script>
The link is opened when the button is clicked.
The link is opened when the button is clicked.

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.

When the button is clicked, the event listener is called, which in turn calls window.open(), which opens the specified link in a new tab.

How to Remove Special Characters From a String in JavaScript

To remove all special characters from a string, call the replace() method on the string, passing a whitelisting regex and an empty string as arguments, i.e., str.replace(/^a-zA-Z0-9 ]/g, ''). The replace() method will return a new string that doesn’t contain any special characters.

For example:

const str = 'milk and @#$%&!bread';

const noSpecialChars = str.replace(/[^a-zA-Z0-9 ]/g, '');

console.log(noSpecialChars); // milk and bread

The String replace() method searches a string for a value (substring or regular expression), and returns a new string with the value replaced by a substring. It doesn’t modify the original string.

The square brackets in the regular expression ([]) indicates a character class. Only characters that are enclosed in it will be matched.

But after placing the caret (^) as the first character in the square bracket, only characters that are not enclosed in the square bracket will be matched.

After the caret, we specify:

  • ranges for lowercase (a-z) and uppercase (A-Z) letters.
  • a range for digits from 0-9.
  • a space character (' ').

So the regex matches any character is not a lowercase or uppercase letter, digit or space, and the replace() method returns a new string with all of these characters removed from the original string.

The g (global) flag specifies that every occurrence of the pattern should be matched.

If we don’t pass a global flag, only the first special character in the string will be matched and removed.

const str = 'milk and @#$%&!bread';

// 👇 No 'g' flag in regex
const noSpecialChars = str.replace(/[^a-zA-Z0-9 ]/, '');

// 👇 Only first special character removed
console.log(noSpecialChars); // milk and #$%&!bread

Shorten regular expression with \w character.

We can shorten this regular expression a bit with the \w character.

const str = 'milk and @#$%&!bread';

const noSpecialChars = str.replace(/[^\w ]/g, '');

console.log(noSpecialChars); // milk and bread

The \w character matches uppercase and lowercase Latin letters, digits, and underscores.

Since \w matches underscores, it can’t be used on its own to remove this special character from a string.

const str = '_milk_ _and _@#$%&!_bread_';

const noSpecialChars = str.replace(/[^\w ]/g, '');

console.log(noSpecialChars); // _milk_ _and_ _bread_

We’ll need a different regex to remove the underscores:

const str = '_milk_ _and _@#$%&!_bread_';

const noSpecialChars = str.replace(/([^\w ]|_)/g, '');

console.log(noSpecialChars); // milk and bread

The pipe symbol (|) allows either of two patterns to be matched in a string, similar to a character class. To use the pipe symbol we need to wrap the two patterns in parentheses (( and )), which is what we did.

How to Get the Value of a Form Input on Submit in React

To get the value of form input on submit in React:

  1. Create a state variable to store the value of the input.
  2. Set an onChange event handler on the input to update the state variable when the input’s value changes.
  3. Set an onSubmit event handler on the form element.
  4. Access the value of the input field in the onSubmit event handler.

For example:

App.js

import { useState } from 'react';

export default function App() {
  const [firstName, setFirstName] = useState('');
  const [lastName, setLastName] = useState('');
  const [message, setMessage] = useState('');

  const handleSubmit = (event) => {
    event.preventDefault();

    setMessage(`Hello ${firstName} ${lastName}!`);
    setFirstName('');
    setLastName('');
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        id="firstName"
        name="firstName"
        value={firstName}
        placeholder="First Name"
        onChange={(event) =>
          setFirstName(event.target.value)
        }
      />

      <br />
      <br />

      <input
        type="text"
        id="lastName"
        name="lastName"
        value={lastName}
        placeholder="Last Name"
        onChange={(event) => {
          setLastName(event.target.value);
        }}
      />

      <br />
      <br />

      <button type="submit">Submit</button>

      <br />
      <br />

      <h2>{message}</h2>
    </form>
  );
}
The input values are used to display a message on form submit.

With the useState() hook we create a state variable to store the current value of each input field. We also created another state variable (message) that will be updated with the values of the input fields after the user submits the form.

We set an inline onChange event handler on each input field to make the handler get called whenever the input field changes. In each handler, we use the target property of the Event object the handler receives to access the input element object. The value property of this object contains the input value, so we pass it to the state update function to update the value of that particular input.

The button element in the form has a type of submit, so every time the user clicks it, the submit event is triggered. We set an onSubmit event handler on the form to listen to this event. In this handler, we call preventDefault() on the Event object, to prevent the page from refreshing when the form is submitted.

To get the input values in this event handler after the form is submitted, we simply access the firstName and lastName state variables.

Get input value on form submit with event.target

We can also get the value of a form input on submit using the target property of the Event object. This is useful in cases where we don’t track the input value with a state variable, i.e., an uncontrolled input.

App.js

import { useState } from 'react';

export default function App() {
  const [message, setMessage] = useState('');

  const handleSubmit = (event) => {
    event.preventDefault();

    const firstName = event.target.firstName.value;
    const lastName = event.target.lastName.value;
    setMessage(`Hello ${firstName} ${lastName}!`);

    event.target.reset();
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        id="firstName"
        name="firstName"
        placeholder="First Name"
      />

      <br />
      <br />

      <input
        type="text"
        id="lastName"
        name="lastName"
        placeholder="Last Name"
      />

      <br />
      <br />

      <button type="submit">Submit</button>

      <br />
      <br />

      <h2>{message}</h2>
    </form>
  );
}

In an onSubmit event handler, the target property of the Event object returns the form element object (of type HTMLFormElement).

Because we set the name prop on the input element, the form element object will contain a property with the same name that returns the input element object, i.e., after setting name to firstName on an input element, we can access the element object for this input with the firstName property on the form element object.

After getting the value of each input and displaying the message, we call the reset() method on the form element object to restore the default values of the form’s input elements. This is how we clear the text in the input fields in this example since they’re not controlled by state variables.

Get input value on form submit with ref

We can also use a component ref to get the value of an uncontrolled form input on submit in React.

App.js

import { useState, useRef } from 'react';

export default function App() {
  const [message, setMessage] = useState('');
  const firstNameRef = useRef(undefined);
  const lastNameRef = useRef(undefined);

  const handleSubmit = (event) => {
    event.preventDefault();

    const firstName = firstNameRef.current.value;
    const lastName = lastNameRef.current.value;

    setMessage(`Hello ${firstName} ${lastName}!`);

    event.target.reset();
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        id="firstName"
        name="firstName"
        placeholder="First Name"
        ref={firstNameRef}
      />

      <br />
      <br />

      <input
        type="text"
        id="lastName"
        name="lastName"
        placeholder="Last Name"
        ref={lastNameRef}
      />

      <br />
      <br />

      <button type="submit">Submit</button>

      <br />
      <br />

      <h2>{message}</h2>
    </form>
  );
}

The data in a controlled input is handled by React state, but for an uncontrolled input, it is handled by the DOM itself. This is why the input in this example above doesn’t have a value prop or onChange event handler set. Instead, we access the input field’s value with a React ref. The DOM updates this value when the text in the input is changed.

For each input, we create a ref object with the useRef() hook and set it to the ref prop of the input. Doing this sets the current property of the ref object to the DOM object that represents the input element.

useRef() returns a mutable ref object that doesn’t change value when a component is updated. Also, modifying the value of this object’s current property doesn’t cause a re-render. This is in contrast to the setState update function returned from useState().

Although the React documentation recommends using controlled components, uncontrolled components offer some advantages. You might prefer them if the form is very simple and doesn’t need instant validation, and values only need to be accessed when the form is submitted.

How to Subtract 6 Months From a Date in JavaScript

To subtract 6 months from a date:

  1. Call the getMonth() method on the date to get the months.
  2. Subtract 6 from the return value of getMonth().
  3. Pass the result of the subtraction to the setMonth() method.

For example:

function subtract6Months(date) {
  date.setMonth(date.getMonth() - 6);

  return date;
}

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

const newDate = subtract6Months(date);

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

Our subtract6Months() function takes a Date object and the number of months to subtract as arguments. It returns the same Date object with 6 months subtracted.

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 subtracted would decrease the year of the date, setMonths() will automatically update the date information to reflect this.

// January 10, 2022
const date = new Date('2022-01-10T00:00:00.000Z');

date.setMonth(date.getMonth() - 6);

// July 10, 2021
console.log(date); // 2021-07-10T00:00:00.000Z

In this example, we subtract 6 months from a date in January 2022. This makes the year automatically get rolled back to 2021 by setMonth().

Avoid side-effects

The setMonth() mutates the Date object it is called on. This introduces a side effect into our subtract6Months() 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 subtract6Months(date) {
  // 👇 Make copy with "Date" constructor
  const dateCopy = new Date(date);

  dateCopy.setMonth(dateCopy.getMonth() - 6);

  return dateCopy;
}

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

const newDate = subtract6Months(date);

// February 13, 2022
console.log(newDate); // 2022-02-13T00:00:00.000Z

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

Alternatively, we can use the subMonths() function from the date-fns NPM package to quickly subtract 6 months from a date. It works like our pure subtractMonths() function. subMonths() takes a Date object and the number of months to subtract as arguments. It returns a new Date object with the months subtracted.

import { subMonths } from 'date-fns';

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

const newDate = subMonths(date, 6);

// January 26, 2022
console.log(newDate); // 2022-01-26T00:00:00.000Z

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

Note that the subMonths() function returns a new Date object without modifying the one passed to it.

How to Subtract Months From a Date in JavaScript

1. Date getMonth() and setMonth() methods

To subtract months from a date in JavaScript:

  1. Call the getMonth() method on the Date to get the months.
  2. Subtract the months.
  3. Pass the result of the subtraction to the setMonth() method.

For example:

function subtractMonths(date, months) {
  date.setMonth(date.getMonth() - months);
  return date;
}

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

const newDate = subtractMonths(date, 3);

// May 13, 2022
console.log(newDate); // 2022-05-13T00:00:00.000Z

Our subtractMonths() function takes a Date object and the number of months to subtract as arguments. It returns the same Date object with the months subtracted.

The Date getMonth() method 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 subtracted would decrease the year of the date, setMonth() will automatically update the date information to reflect this.

// January 10, 2022
const date = new Date('2022-01-10T00:00:00.000Z');

date.setMonth(date.getMonth() - 2);

// November 10, 2021: year decreased by 1
console.log(date); // 2021-11-10T00:00:00.000Z

In this example, we subtracted 2 months from a date in January 2022. This makes setMonth() automatically roll the year back to 2021.

Avoid side-effects

The setMonth() method mutates the Date object it is called on. This introduces a side effect into our subtractMonths() 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 subtractMonths(date, months) {
  // 👇 Make copy with "Date" constructor
  const dateCopy = new Date(date);

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

  return dateCopy;
}

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

const newDate = subtractMonths(date, 3);

// May 13, 2022
console.log(newDate); // 2022-05-13T00:00:00.000Z

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

Alternatively, we can use the subMonths() function from the date-fns NPM package to quickly subtract months from a date. It works like our pure subtractMonths() function.

import { subMonths } from 'date-fns';

// June 27, 2022
const date = new Date('2022-06-27T00:00:00.000Z');

const newDate = subMonths(date, 4);

// February 27, 2022
console.log(newDate); // 2022-02-27T00:00:00.000Z

// 👇 Original not modified
console.log(date); // 2022-06-27T00:00:00.000Z

How to Add a Class Conditionally in Vue

To add a class conditionally to an element in Vue, set the class prop to a JavaScript object where for each property, the key is the class name, and the value is the boolean condition that must be true for the class to be set on the element.

<p
  v-bind:class="{
    'class-1': class1,
    'class-2': class2,
  }"
>
  Coding
</p>

Here’s a complete example:

App.vue

<template>
  <div id="app">
    <input
      type="checkbox"
      name="class-1"
      v-model="class1"
    />
    <label for="class-1">Class 1</label>

    <br />

    <input
      type="checkbox"
      name="class-2"
      v-model="class2"
    />
    <label for="class-2">Class 2</label>

    <!-- 👇 Add classes conditionally -->
    <p
      v-bind:class="{
        'class-1': class1,
        'class-2': class2,
      }"
    >
      Coding
    </p>
    <p
      v-bind:class="{
        'class-1': class1,
        'class-2': class2,
      }"
    >
      Beauty
    </p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      class1: false,
      class2: false,
    };
  },
};
</script>

<style>
.class-1 {
  font-size: 2em;
  font-weight: bold;
}

.class-2 {
  color: blue;
  text-transform: uppercase;
}
</style>
Setting a class conditionally in Vue.
The classes are only applied when their respective checkboxes are checked.

The class-1 class will only present on the element if the class1 variable is true, and the class-2 class will only be present if the class2 variable is true. The values of these variables are determined by the current checked state of their respective checkboxes since we use v-model to set up a two-way binding between the variables and the checkboxes.

Use :class shorthand

We can use :class as a shorthand for v-bind:class.

<p
  :class="{
    'class-1': class1,
    'class-2': class2,
  }"
>
  Coding
</p>
<p
  :class="{
    'class-1': class1,
    'class-2': class2,
  }"
>
  Beauty
</p>

Pass object as computed property

The JavaScript object passed doesn’t have to be inline. It can be stored as a computed property in the Vue component instance.

<template>
  <div id="app">
    ...
    <!-- 👇 Add classes conditionally -->
    <p :class="classObject">Coding</p>
    <p :class="classObject">Beauty</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      class1: false,
      class2: false,
    };
  },
  computed: {
    // 👇 Computed object property
    classObject() {
      return {
        'class-1': this.class1,
        'class-2': this.class2,
      };
    },
  },
};
</script>
...

Add both static and dynamic classes

We can set the class prop on the same element twice, once to add static classes, and once to add the dynamic classes that will be present based on certain conditions.

For example:

<template>
  <div id="app">
    <input
      type="checkbox"
      name="class-1"
      v-model="class1"
    />
    <label for="class-1">Class 1</label>

    <br />

    <input
      type="checkbox"
      name="class-2"
      v-model="class2"
    />
    <label for="class-2">Class 2</label>

    <!-- 👇 Add classes conditionally and statically -->
    <p
      class="static-1 static-2"
      :class="{ 'class-1': class1, 'class-2': class2 }"
    >
      Coding
    </p>
    <p
      class="static-1 static-2"
      :class="{ 'class-1': class1, 'class-2': class2 }"
    >
      Beauty
    </p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      class1: false,
      class2: false,
    };
  },
};
</script>

<style>
.class-1 {
  font-size: 2em;
  font-weight: bold;
}

.class-2 {
  color: blue;
  text-transform: uppercase;
}

/* 👇 Classes to add statically */
.static-1 {
  font-family: 'Segoe UI';
}

.static-2 {
  font-style: italic;
}
</style>
Adding a class conditionally in Vue.
The texts are styled with static classes before being conditionally styled with dynamic classes.

The static-1 and static-2 classes are always applied to the texts, making them italic and changing the font.