0

I have a bottom navigation list of div elements which each contain a svg icon. When the user clicks on an icon I need the given id property to set the state of which the specific content is then rendered. I actually figured it out, but the problem with inline svg is that the passed event.target is either the <div>, the <svg> tag or even further down the <path>. I envision a solution where whenever the user clicks, the event always bubbles up to div.id and gets returned to be set into state.

Do I need to set a click handeler on every childnode manually or is there another way?

Example:

const Nav = () => {
  return (
    <nav>
      <div id="I-WANT-YOU" onClick={event => whatToDoHere(event)}>
         <svg fill="#systemValue">
           <path ....long path .... />
         </svg>
      </div>
      .... repeat 5 times
    </nav>
  )
}

Now I have a dirty solution of setting the svg icon as a background-image: url('path/here.svg'); but the intention with inlining the svg icons is, that I can set user specific fill values which will not be possible with this solution.

NOTE:

  • Yes I am aware of <ul> and <li>, I try to describe the problem as simple as possible.
  • My knowledge on event delegation is limited and I know about about the true parameter on a vanilla click event listener. The onClickCapture React documentation did not help me.
andylib93
  • 133
  • 8
  • Hi, are your sure that the `onClickCapture` is not the way ? Events have two phases. First the event propagates from the window container to the clicked dom element (this is the capture phase). And then the bubbling phase is the event bubbling back up to the window element. If you set a `onClickCapture` on the parent div element then you will receive all the incoming events for any clicked child element. Is it of any help ? If this feels right to you, I will make this an answer. – Antoine Laffargue Jan 13 '21 at 17:18
  • If I use ```onClickCaptue``` on the ```div``` it still targets either the ``````, `````` or ```div```. – andylib93 Jan 13 '21 at 17:29

1 Answers1

1

If you want your children to provide state to the parent, then you need to pass down a function for them to call when they are clicked.

So in the parent, you maintain state with:

const [currentSVG, setCurrentSVG] = useState();

Then when you call your child element, pass in a function as a prop.

 <Item id="1" onClick={(id) => setCurrentSVG(id)} name="SVG 1" />

then in your child, take the function out of the props and put it on the click handler of the div that holds your svg. Then onClick, call the function that you passed in:

const Items = ({ onClick, name, id }) => {
  return (
    <StyledSVGDiv onClick={() => onClick(id)}>
      {name}
      <svg width="100" height="100">
        <circle
          cx="50"
          cy="50"
          r="40"
          stroke="green"
          strokeWidth="4"
          fill="yellow"
        />
      </svg>
    </StyledSVGDiv>
  );
};

Example: https://oh23w.csb.app/

Sir Codes Alot
  • 1,149
  • 8
  • 11