ipenguin67
ipenguin67

Reputation: 1649

Props not being passed down to Material UI button text

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

Answers (1)

Ryan Cogswell
Ryan Cogswell

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>
  );
}

Edit currentTarget

Upvotes: 1

Related Questions