Last updated: Apr 7, 2024
Reading timeยท5 min

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.
export default function App() { const handleClick = event => { console.log(event.target.dataset); // ๐๏ธ "my-btn" console.log(event.target.getAttribute('data-test-id')); // ๐๏ธ Set an 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> ); }

We can also directly set a data attribute on an element by using data-*
syntax.
<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.
event.target.setAttribute('data-foo', 'bar');
The method takes the following 2 parameters:
name - the name of the attribute to be set.value- the value to assign to the attribute.If you need to remove an attribute from the element, you can use the
removeAttribute method.
el.removeAttribute('data-foo');
The removeAttribute method removes the attribute with the specified name from
the element.
The target property on the event gives us a reference to the element that
triggered the event (could be a descendant).
const handleClick = event => { console.log(event.target.dataset); // ๐๏ธ "my-btn" console.log(event.target.getAttribute('data-test-id')); // ๐๏ธ Set an 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 };
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.
const handleClick = event => { console.log(event.currentTarget.dataset); // ๐๏ธ "my-btn" console.log(event.currentTarget.getAttribute('data-test-id')); // ๐๏ธ Set an 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 };
ref to access a DOM element and set its data-attributesAlternatively, you can use a ref to access the DOM element to set its data
attribute.
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 an 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> ); }

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.
const ref = useRef(null);
The hook returns a mutable ref object whose .current property is initialized
to the passed argument.
current property on the ref object to get access to the button element on which we set the ref prop.console.log(ref.current.dataset); // ๐๏ธ Set an 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.
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.
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> ); }

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).
currentTarget property on the event gives us access to the element that the event listener is attached to.event.currentTarget to get data attributes from an EventIf 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.
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> ); }

We used the dataset property to get a Map of strings that contains the data
attributes of the element.
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.
event.currentTarget.dataset.testId = 'updated-test-id';
Map object to a native JS objectIf you need to convert the DOM string Map to a native JavaScript object, you can use the spread syntax (...).
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.
const handleClick = event => { console.log(event.currentTarget.getAttribute('data-test-id')); console.log(event.currentTarget.getAttribute('data-bar')); };
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.