How to Set and get Data Attributes in React

avatar
Borislav Hadzhiev

Last updated: Jan 18, 2023
5 min

banner

# Table of Contents

  1. Setting data attributes in React
  2. Get data attribute from Event object in React

# Setting data attributes in React

To set a data attribute on an element in React, set the attribute directly on the element, e.g. <button data-test-id="my-btn"> or use the setAttribute() method.

You can access the element on the event object or using a ref.

App.js
export default function App() { const handleClick = event => { console.log(event.target.dataset); // ๐Ÿ‘‡๏ธ "my-btn" console.log(event.target.getAttribute('data-test-id')); // ๐Ÿ‘‡๏ธ set attribute event.target.setAttribute('data-foo', 'bar'); console.log(event.target.getAttribute('data-foo')); // ๐Ÿ‘‰๏ธ bar event.target.setAttribute('data-foo', 'baz'); console.log(event.target.getAttribute('data-foo')); // ๐Ÿ‘‰๏ธ baz }; return ( <div> {/* ๐Ÿ‘‡๏ธ set data-test-id attribute */} <button onClick={handleClick} data-test-id="my-btn"> Click </button> </div> ); }

react set data attribute

We can also directly set a data attribute on an element by using data-* syntax.

App.js
<button onClick={handleClick} data-test-id="my-btn"> Click </button>

Notice that we don't camelCase custom data-* properties.

The example shows how to use the setAttribute() method in an event to set or update a data attribute programmatically.

App.js
event.target.setAttribute('data-foo', 'bar');

The method takes the following 2 parameters:

  1. name - the name of the attribute to be set.
  2. value- the value to assign to the attribute.
If the attribute already exists on the element, its value is updated, otherwise, a new attribute is added with the specified name and value.

# Removing a data attribute from an element

If you need to remove an attribute from the element, you can use the removeAttribute method.

index.js
el.removeAttribute('data-foo');

The removeAttribute method removes the attribute with the specified name from the element.

If the attribute doesn't exist on the element, the method returns without throwing an error.

# Accessing an element on which to set data attributes

The target property on the event gives us a reference to the element that triggered the event (could be a descendant).

App.js
const handleClick = event => { console.log(event.target.dataset); // ๐Ÿ‘‡๏ธ "my-btn" console.log(event.target.getAttribute('data-test-id')); // ๐Ÿ‘‡๏ธ set attribute event.target.setAttribute('data-foo', 'bar'); console.log(event.target.getAttribute('data-foo')); // ๐Ÿ‘‰๏ธ bar event.target.setAttribute('data-foo', 'baz'); console.log(event.target.getAttribute('data-foo')); // ๐Ÿ‘‰๏ธ baz };
Whereas the currentTarget property on the event gives us access to the element that the event listener is attached to.

If the target property refers to a descendant element in your scenario and you need access to the element that the event listener is attached to, simply replace target with currentTarget.

App.js
const handleClick = event => { console.log(event.currentTarget.dataset); // ๐Ÿ‘‡๏ธ "my-btn" console.log(event.currentTarget.getAttribute('data-test-id')); // ๐Ÿ‘‡๏ธ set attribute event.currentTarget.setAttribute('data-foo', 'bar'); console.log(event.currentTarget.getAttribute('data-foo')); // ๐Ÿ‘‰๏ธ bar event.currentTarget.setAttribute('data-foo', 'baz'); console.log(event.currentTarget.getAttribute('data-foo')); // ๐Ÿ‘‰๏ธ baz };

# Using a ref to access a DOM element and set its data-attributes

Alternatively, you can use a ref to access the DOM element to set its data attribute.

App.js
import {useRef} from 'react'; export default function App() { const ref = useRef(null); const handleClick = () => { console.log(ref.current.dataset); // ๐Ÿ‘‡๏ธ "my-btn" console.log(ref.current.getAttribute('data-test-id')); // ๐Ÿ‘‡๏ธ set attribute ref.current.setAttribute('data-foo', 'bar'); console.log(ref.current.getAttribute('data-foo')); // ๐Ÿ‘‰๏ธ bar ref.current.setAttribute('data-foo', 'baz'); console.log(ref.current.getAttribute('data-foo')); // ๐Ÿ‘‰๏ธ baz }; return ( <div> <button ref={ref} onClick={handleClick} data-test-id="my-btn"> Click </button> </div> ); }

using ref to access dom element and set its data attribute

This code sample achieves the same result, however, we used a ref to access the DOM element.

The useRef() hook can be passed an initial value as an argument.

App.js
const ref = useRef(null);

The hook returns a mutable ref object whose .current property is initialized to the passed argument.

Notice that we have to access the current property on the ref object to get access to the button element on which we set the ref prop.
App.js
console.log(ref.current.dataset); // ๐Ÿ‘‡๏ธ set attribute ref.current.setAttribute('data-foo', 'bar');

When we pass a ref prop to an element, e.g. <button ref={myRef} />, React sets the .current property of the ref object to the corresponding DOM node.

The current property on the ref gives us access to the button element, so we can set a data attribute on the element with ref.current.setAttribute('data-foo', 'bar').

Make sure to access the ref in the useEffect hook or when an event occurs because if you try to access the ref immediately, it might not be set up yet or the element might not be in the DOM yet.

# Get data attribute from Event object in React

Use the target.dataset property to access data attributes from the event object in React.

The dataset property provides read and write access to the custom data attributes of the element.

The property returns a Map of strings that can be converted to an object.

App.js
export default function App() { const handleClick = event => { console.log(event.target.dataset); console.log(event.target.getAttribute('data-test-id')); }; const handleChange = event => { console.log(event.target.dataset); console.log(event.target.getAttribute('data-attr')); }; return ( <div> <button onClick={handleClick} data-test-id="my-btn"> Click </button> <input onChange={handleChange} data-attr="my-input" /> </div> ); }

get data attribute from event

We set the onClick prop on the button, so every time it is clicked, the handleClick function is invoked.

The target property on the event gives us a reference to the element that triggered the event (could be a descendant).

Whereas the currentTarget property on the event gives us access the element that the event listener is attached to.

# Using event.currentTarget to get data attributes from an Event

If the target property refers to a descendant element in your scenario and you need access to the element that the event listener is attached to, simply replace target with currentTarget.

App.js
export default function App() { const handleClick = event => { console.log(event.currentTarget.dataset); console.log(event.currentTarget.getAttribute('data-test-id')); }; const handleChange = event => { console.log(event.currentTarget.dataset); console.log(event.currentTarget.getAttribute('data-attr')); }; return ( <div> <button onClick={handleClick} data-test-id="my-btn"> Click </button> <input onChange={handleChange} data-attr="my-input" /> </div> ); }

using event current target to get data attribute

We used the dataset property to get a Map of strings that contains the data attributes of the element.

The property returns a read-only Map of strings containing the custom data attributes of the element.

The dataset property itself is read-only. If you need to update a specific property, you must access the nested property.

App.js
event.currentTarget.dataset.testId = 'updated-test-id';

# Converting the DOM Map object to a native JS object

If you need to convert the DOM string Map to a native JavaScript object, you can use the spread syntax (...).

App.js
const handleClick = event => { const map = event.currentTarget.dataset; const obj = {...map}; console.log(obj); };

An alternative approach is to use the getAttribute method on the element.

App.js
const handleClick = event => { console.log(event.currentTarget.getAttribute('data-test-id')); console.log(event.currentTarget.getAttribute('data-bar')); };
Notice that when passing an attribute name to the getAttribute method, we have to provide the complete name, including the data- part.

As opposed to when accessing a property on the dataset Map, where the data- part is excluded.

If the attribute is not found on the DOM element, the getAttribute method will return null or an empty string.

If you get the warning prop spreading is forbidden, click on the link and follow the instructions.

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.

Copyright ยฉ 2024 Borislav Hadzhiev