Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Adding event listeners using useRef inside a loop

I’m writing a React component that accepts some data as an array and renders them. However, I need to add some event listeners to it. The functions I’ll be passing to the event listeners should depend on the data. Basically, the rendered items and their behavior should be completely data-driven.

I wrote this piece of code that adds event listeners, however it seems like it keeps overwriting the event listeners and I always get the function from the last iteration.

const App = () => {
 const data = ['item1', 'item2', 'item3', 'item4', 'item5'];
 const itemRef = React.useRef(data.map((x) => React.createRef(x)));

 React.useEffect(() => {
  for (var i = 0; i < itemRef.current.length; i++) {

   // need to define a function here that will 
   // accept data[i] as a parameter.
   // That unique function would be added 
   // to event listener on each iteration 

   itemRef.current[i].current.addEventListener('click', () => {
    console.log(`clicked data:${i}`);
   });
  }
 }, []);

 return (
  <div className="App">
   {data.map((x, i) => {
    return (
     <div className='item' ref={itemRef.current[i]} key={data[i]}>
      {x}
     </div>
    );
   })}
  </div>
 );
}
ReactDOM.render(
    <App/>,
    document.getElementById("root")
);
.App {
  text-align: center;
}

.item{
  border: 1px solid black;
  width: 300px;
  margin: 10px auto;
  border-radius: 3px;
  cursor: pointer;
}
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"></script>

Ideally, in that () => {console.log(i)} section (inside addEventListener) I want to pass a function that would be unique on each iteration.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Am I taking the right approach with this? Can this code be amended so if I click on item 3 it logs 3 (not 5)?

>Solution :

You needn’t resort to refs in this instance, an onClick will work, you can add in a handler, or you can define a function on the fly like below:

const App = () => {
 const data = ['item1', 'item2', 'item3', 'item4', 'item5'];

 return (
  <div className="App">
   {data.map((x, i) => {
    return (
     <div className='item' onClick={()=>{console.log("item data", x)}} key={data[i]}>
      {x}
     </div>
    );
   })}
  </div>
 );
}
ReactDOM.render(
    <App/>,
    document.getElementById("root")
);
.App {
  text-align: center;
}

.item{
  border: 1px solid black;
  width: 300px;
  margin: 10px auto;
  border-radius: 3px;
  cursor: pointer;
}
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"></script>
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading