W artykule przedstawię w jaki sposób możemy dostać się do własnych atrybutów oraz atrybutu data-* w elementach HTML przy wykorzystaniu React. W atrybutach możemy przekazać dodatkowe dane, które wykorzystamy np. w logice w aplikacji.
Trzeba jednak wspomnieć, że przekazywanie danych przez atrybuty HTML nie jest rekomendowanym sposobem, o czym możemy przeczytać na oficjalnej stronie Reacta. Warto natomiast wiedzieć, że taka możliwość istnieje. Warto też wiedzieć jak z tego skorzystać, bo być może gdzieś zobaczymy podobny fragment kodu w Reactowych aplikacjach.
Czym są atrybuty?
W przypadku HTMLowych elementów atrybutem będzie zarówno href w elemencie <a> lub src w elemencie <img> itd…
My z kolei skupimy się na atrybucie data-*, który możemy dodać do elementu HTML. Z tego atrybutu będziemy korzystać w naszym przykładzie.
<ul>
<li data-gender="male">Adam</li>
<li data-gender="male">Zenek</li>
<li data-gender="male">Mirek</li>
<li data-gender="female">Basia</li>
<li data-gender="female">Zosia</li>
<li data-gender="female">Czesia</li>
</ul>
Wykorzystanie w React
Wyobraźmy sobie, że dla powyższego przykładu i listy osób chcemy zrobić obsługę głosowania. Każda osoba posiada id oraz daną pomocniczą, służącą np. do statystyk. Zmodyfikujemy nieco nasz kod dodając teraz atrybut id.
<ul> <li data-id="1" data-gender="male">Adam</li> <li data-id="2" data-gender="male">Zenek</li> <li data-id="3" data-gender="male">Mirek</li> <li data-id="4" data-gender="female">Basia</li> <li data-id="5" data-gender="female">Zosia</li> <li data-id="6" data-gender="female">Czesia</li> </ul>
Przeróbmy to teraz, aby było bardziej „Reactowo”. 🙂
function App() {
const people = [
{id: 1, name: 'Adam', gender: 'male'},
{id: 2, name: 'Zenek', gender: 'male'},
{id: 3, name: 'Mirek', gender: 'male'},
{id: 4, name: 'Basia', gender: 'female'},
{id: 5, name: 'Zosia', gender: 'female'},
{id: 6, name: 'Czesia', gender: 'female'},
];
return (
<ul>
{people.map((person) => (
<li key={person.id} data-id={person.id} data-gender={person.gender}>
{person.name}
</li>
))}
</ul>
);
}
Musimy teraz sprawić, aby po kliknięciu w dany <li> nastąpiło wywołanie eventu z odpowiednim id elementu.
Dodajemy sobie kawałek kodu, w którym w realnej aplikacji byłaby obsługa logiki. Dodajemy obsługę onClick oraz metodę obsługującą głosowanie.
<li
key={person.id}
data-id={person.id}
data-gender={person.gender}
onClick={vote}
>
{person.name}
</li>
const vote = (event) => {
console.log(event);
console.log(event.target.dataset);
}
Jeżeli włączycie konsolę i kliknięcie w dany element listy, powinniście widzieć w niej coś w stylu:
Class {dispatchConfig: {…}, _targetInst: FiberNode, nativeEvent: MouseEvent, type: "click", target: li, …}
DOMStringMap {id: "6", gender: "female"}
gender: "female"
id: "6"
__proto__: DOMStringMap
Jak widzicie, uzyskaliśmy dostęp do atrytubów data-gender oraz data-id. W ten sposób możemy wykorzystać te dane do logiki.
Możemy również w elegancki sposób użyć destrukturyzacji, a potem bezpośrednio użyć wartości z data-id oraz data-gender.
const vote = (event) => {
const { id, gender } = event.target.dataset;
console.log(id);
console.log(gender);
}
Własny atrybut
Możemy również dodać własny atrybut i odwołać się do jego wartości. W poniższym kodzie dodaliśmy atrybut wraz z wartością mojjakisatrybut="some value". Dostęp do niego odbywa się poprzez event.target.getAttribute('mojjakisatrybut').
const vote = (event) => {
console.log(event.target.getAttribute('mojjakisatrybut'))
}
return (
<ul>
{people.map((person) => (
<li
key={person.id}
mojjakisatrybut="some value"
onClick={vote}
>
{person.name}
</li>
))}
</ul>
)
Pamiętajmy, aby własne atrybuty nazywać małymi literami, o czym informuje nas poniższy warning.
Warning: React does not recognize the `mojJakisAtrybut` prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase `mojjakisatrybut` instead. If you accidentally passed it from a parent component, remove it from the DOM element.
React i atrybuty
Na stronie Reacta możemy znaleźć informację, w której autorzy nie zachęcają do przekazywania danych poprzez własne atrybuty.
Nawet jeżeli używamy atrybutu data-* (a nie własnego atrybutu), zapewne lepszym rozwiązaniem będzie przechowywanie danych w state komponentu lub zewnętrznym „store”. Możemy o tym przeczytać tutaj: https://pl.reactjs.org/blog/2017/09/08/dom-attributes-in-react-16.html
Niemniej jednak warto wspomnieć, że takie możliwości istnieją. Może gdzieś spotkamy się z takim rozwiązaniem, będziemy wtedy wiedzieć skąd to się bierze i jak sobie z tym poradzić.
Do następnego, dzięki!
Źródła:
Obraz: https://unsplash.com/photos/eo3Xr2yhYVw
Oficjalna www React i trochę informacji na temat atrybutów: https://pl.reactjs.org/blog/2017/09/08/dom-attributes-in-react-16.html