Reputation: 1649
I have a scenario in my app where I use data attributes on buttons to capture certain contextual information in the modal that is launched by pressing the button. This relies on the data attributes being available on e.target.dataset
. The problem is if I click on the part of the button with text, the target is a that appears to be generated by Material-UI but which doesn't contain the props I passed down to the button.
Here's my button implementation (Button.js) [SmallButton and LargeButton are styled versions of the Material Button]:
const Button = ({ buttonText, buttonSize, handleClick, pink, ...props }) => {
return (
<>
{buttonSize === 'large' ? (
<LargeButton
variant="contained"
fullWidth={true}
size="large"
onClick={handleClick}
pink={pink}
{...props}
>
{buttonText}
</LargeButton>
) : (
<SmallButton
variant="contained"
size="small"
onClick={handleClick}
pink={pink}
{...props}
>
{buttonText}
</SmallButton>
)}
</>
);
};
This is where the button is used:
<AddContainer flexDirection="column">
<Label {...props}>Add {type}</Label>
<Button
buttonSize="small"
buttonText="+ Add"
pink="true"
data-show-only={lowerCase(type)} // this needs to come through in e.target.dataset when button clicked
onClick={launchModal}
/>
</AddContainer>
<ModalContainer
open={open}
context={context}
handleClose={closeModal}
initialScreen="Add Exercise"
addWorkout={addWorkout}
/>
The context
object above should include a property called showOnly
. Here is the custom hook where we create the context object.
const useModal = (initialValues = {}) => {
const [open, setOpen] = useState(initialValues);
const [context, setContext] = useState({});
const launchModal = e => {
const targetContext = { ...e.target.dataset };
setContext(targetContext);
setOpen(true);
};
const closeModal = e => {
setOpen(false);
setContext({});
};
return {
open,
context,
launchModal,
closeModal,
};
};
If I click on the outside of the button, this works as designed, with e.target.dataset
containing a showOnly
property that is passed on to the context
object. If you click on the text, e.target
is a and e.target.dataset
is empty.
Upvotes: 1
Views: 277
Reputation: 81026
You want to use currentTarget
instead of target
.
From https://developer.mozilla.org/en-US/docs/Web/API/Event/currentTarget:
The currentTarget read-only property of the Event interface identifies the current target for the event, as the event traverses the DOM. It always refers to the element to which the event handler has been attached, as opposed to Event.target, which identifies the element on which the event occurred and which may be its descendant.
Here's a little example that you can use to see the difference in the console logs:
import React from "react";
import Button from "@material-ui/core/Button";
export default function App() {
return (
<div className="App">
<Button
data-test="1"
onClick={e => {
console.log("target", e.target.dataset);
console.log("currentTarget", e.currentTarget.dataset);
}}
>
Hello
</Button>
</div>
);
}
Upvotes: 1