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