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.