React TypeScript get Data Attribute From Click Event
Asked Answered
O

4

15

So I have a React component with a button which has a click handler which uses the data-* attribute. If this was straight React then I know how to get the value from the data-* attribute. However I am learning how to use TypeScript so I have no idea how to get access to this attribute. So what is the best way to get access to the data-* attribute using TypeScript?

This is my JSX code for the button:

<button type="button" className="NavLink" data-appMode={ AppMode.MAIN } onClick={ this.handleAppModeClick.bind(this) }>Main</button>

This is my handler for the click event:

handleAppModeClick(e: React.MouseEvent<HTMLElement>) {
    // What code should go here to access the data-appMode attribute?
}
Ortiz answered 30/10, 2019 at 21:53 Comment(0)
I
23

Use e.currentTarget and then use HTML standard method getAttribute. No coercion necessary.

const appMode = e.currentTarget.getAttribute('data-appmode');

(note lowercase in the attribute name to avoid warnings from react)

currentTarget is already correctly typed.

If you read the definitions of React's event types you can see that MouseEvent extends SyntheticEvent, which extends BaseSyntheticEvent, which includes the property target and currentTarget, among others. The HTMLElement type you provide gets applied to currentTarget, so you have access to all the right stuff. If you use target you'll get a compile error about getAttribute not being valid for type EventTarget.

What's the difference?

The currentTarget is the element where you're putting your handler, onClick. The target is where the event originally came from (more here). This is not necessarily the same because events bubble up. See the PR referenced in the type definitions file for a complete discussion on why they're typed differently.

Iila answered 30/10, 2019 at 22:37 Comment(2)
Thanks Chris! I wasn't aware that there is currentTarget existing inside event together with regular target.Diversify
currentTarget does not work in case of Event Delegation pattern.Comrade
A
2

You most likely will have to use as syntax , depending which property you want to access on e.target.

handleAppModeClick(e: React.MouseEvent) {
    const appMode = (e.target as HTMLButtonElement).getAttribute('data-appMode');
}
Age answered 30/10, 2019 at 22:22 Comment(1)
Coercion/as is unnecessary, see my answer.Iila
C
1

Using typescript I've recently learnt of the following approach:

type TabsProps = {
  activeTab: string,
  items: string[],
  setActiveTab: (i: string) => void,
}

const Tabs = ({ items, activeTab, setActiveTab }: TabsProps) => {
  const onClick: React.MouseEventHandler<HTMLElement> = (e) => {
    setActiveTab(e.currentTarget.dataset.id)
    //console.log(e) // <a data-id="0" class="active nav-link">Info</a>
  }

  return (
    <Nav tabs >
        {
            items.map((x, i) => (
                <NavItem key={i}>
                    <NavLink className={activeTab === i.toString() ? 'active' : ''} onClick={onClick} data-id={i}>{x}</NavLink>
                </NavItem>
            ))
        }
    </Nav >
  );
}
Chichi answered 10/7, 2020 at 8:38 Comment(0)
H
0

In your event function you have e variable, e represents an event fired by clicking the button, e has a target property so, in order to access an attribute from the element you should do:

handleAppModeClick(e: React.MouseEvent<HTMLElement>) {
    const target = e.target as HTMLElement;
    let attr = target.getAttribute("data-attribute-name-here");
    //do something

}
Hypaesthesia answered 30/10, 2019 at 22:13 Comment(2)
Nope that is for using straight React. I am using React with TypeScript which uses a different way. I get this error when I try your code: Property 'getAttribute' does not exist on type 'EventTarget'.Ortiz
Yeah you're right, you should cast the target first, mb.Hypaesthesia

© 2022 - 2024 — McMap. All rights reserved.