1

I'm experiencing a weird response by my onClick event handling.

I have a list of user boxes, which on click, I'm attempting to navigate the client to that specific user's page ( as if - navigate("/farmershop/" + e.target.id) )

I am debugging by console.logg my e.target.id, I only get the id (which I attempt to retrieve) printed when I click on certain areas in the user box. In case I don't press that specific part in the box (on the image), I get an empty string.

These are my functions responsible for stated task:

const handle_clicked_farmer = (e) => {
    console.log(e.target.id);
      navigate("/farmershop/" + e.target.id);
  }

  const createTopFarmers = () => {
    return top_n_farmers.map((farmer) => ( // on click take to farmer's page.
      <Stack  sx={{marginTop: "3%", background: "green", marginLeft:"5%", width: "400px", borderRadius:"5px", boxShadow: "2px 3px 8px black"}}>
        
        <Box sx={{marginLeft:"2%", cursor: "pointer" }} onClick={handle_clicked_farmer} id={farmer.id}>
        <Typography  sx={{fontFamily: "Amatic SC", letterSpacing: "2px", fontSize: "50px", fontWeight: 700}}>{farmer.firstname}</Typography>
        <Typography  sx={{fontFamily: "Amatic SC", letterSpacing: "2px", fontSize: "50px", fontWeight: 700, marginTop: "-5%"}}>{farmer.lastname}</Typography>
        <img src={farmer.img} style={{width: "100px", borderRadius: "300px", border: "2px solid black"}}/>
        <Typography  sx={{fontFamily: "Amatic SC", letterSpacing: "2px", fontSize: "20px", fontWeight: 700, marginTop: "-5%"}}>location: {farmer.location}</Typography>
        </Box>
        
        <Box>
        {farmer.likes} likes
        </Box>
        <Box  sx={{backgroundColor: "green"}}>
          <Typography  sx={{fontFamily: "Amatic SC", fontSize: "25px"}}>{farmer.about}</Typography>

        </Box>
      </Stack>
    ));
  };

any ideas what might be the issue?

regards!

dani_l_n
  • 376
  • 1
  • 11
  • 1
    You can only have one element with the farmer id. You may have to use data attributes instead. – Andy Oct 31 '22 at 15:22
  • Instead of logging `e.target.id` you should log `e.target`. – Andreas Oct 31 '22 at 15:23
  • because the target is the item you click on, it is not the item with the event listener that is attached. So if you click on a child, you get the child element. `e.target.closest('[id]').id` or `e.currentTarget.id`, but in the end, it is weird you are using React like this. This is not a great React pattern. – epascarello Oct 31 '22 at 15:25
  • 1
    Did you try the ```e.currentTarget``` ? – Matthieu Oct 31 '22 at 15:26
  • thanks! it works! what's the difference between target and currentTarget? ;[ I mean, the name quite implies it, I just don;'t understand the usage of target then. – dani_l_n Oct 31 '22 at 15:29
  • @dani_l_n The difference is that "target" is the DOM element where your user really clicked. 'currentTarget' is the DOM element source of the event (where your onClick is declared) – Matthieu Oct 31 '22 at 15:54
  • 1
    @dani_l_n And, i forgot, you are welcome :P – Matthieu Oct 31 '22 at 16:07

2 Answers2

3

First!

e.target is a DOM element, so e.target.id is the ID of the DOM element. Having a prop id={id} in a JSX component DO NOT guarantee you that the component will actually render a DOM element with the provided id

Second!

Speaking of DOM element, the id must be uniq on the page

So maybe for you, best would be to have something like:


const handle_clicked_farmer = id => () => {
  navigate("/farmershop/" + id);
}
  const createTopFarmers = () => {
    return top_n_farmers.map((farmer) => ( // on click take to farmer's page.
      ...
      <Box onClick={handle_clicked_farmer(farmer.id)}>
       ...

dbuchet
  • 1,561
  • 1
  • 5
  • 7
  • Is currentTarget is not a DOM element? Thanks for your answer! – dani_l_n Oct 31 '22 at 15:33
  • events are DOM based, so currentTarget is also a DOM element. You can find the difference in this thread: https://stackoverflow.com/questions/10086427/what-is-the-exact-difference-between-currenttarget-property-and-target-property – dbuchet Oct 31 '22 at 15:36
1

There are a few things at play here, chief among which is likely that Events are Synthetic with React.

You could a more sure-fire way of getting the farmer id by wrapping (also known as currying) your onClick function like so:

const handle_clicked_farmer = (farmerId) => () => {
  navigate("/farmershop/" + farmerId);
}

With the onClick looking like this instead:

<Box sx={{marginLeft:"2%", cursor: "pointer" }} onClick={handle_clicked_farmer(farmer.id)} id={farmer.id}>

At the same time you can do away with relying on the Synthetic Event

Harrison
  • 1,654
  • 6
  • 11
  • 19