Home > Software engineering >  Inline functions in map
Inline functions in map

Time:10-23

What is the most performant way to avoid an inline function in a loop:

const SomeComponent = () => {
  const handler = (idx) => console.log(idx);
  return (<>
    [...Array(100)].map((_, index) => (
      <div onClick=(() => handler(index))>Click me {index}</div>
    </>);
}

Guess this is a bit overengineering

const OtherComp = ({ index, onClick, children }) => {
  const handle = () => { onClick(index); }
  return <div onClick={handle}>{children}<div/>
} 

const SomeComponent = () => {
  const handler = useCallback((idx) => console.log(idx), []);
  return (<>
    [...Array(100)].map((_, index) => (
      <OtherComp onClick=(handler)>Click me {index}</div>
    </>);
}

The "issues" I was thinking about were/are:

  • garbage collector (almost don't care)
  • creation of the "same" function in a loop
  • re-rendering of all children each for each click as the input prop has changed - let's say that click is changing the selected div

CodePudding user response:

As long as the handler isn't too complicated, you could as well define it inside the map, and then refer to it directly in the onClick. To me personally, that even makes it clearer what is going to happen, because I don't have to make the mental jump from one function to the next to find that out.

Working demo:

const SomeComponent = () => {
  return (
    [...Array(100)].map((_, index) => {
      const handler = () => console.log(index);
      return <div onClick={handler}>Click me {index}</div>;
    })
  );
}

ReactDOM.render(<SomeComponent />, document.getElementById('react'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id="react"></div>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

PS - I had to make some small changes because your code was not syntactically correct.

CodePudding user response:

I think that's perfectly fine. It's exceedingly unlikely to have any performance impact at all. But if it's something you're concerned about, since the index is scoped inside the .map callback, the only other option I can think of is for the handler to examine its surrounding DOM to get the index:

<div onClick={handler}>Click me {index}</div>
const handler = (e) => {
  const div = e.currentTarget;
  const index = [...div.parentElement.children].indexOf(div);
  console.log(index);
};

But using {() => handler(index)} is a much more React-ish style, and is a lot easier to read and make sense of - I'd prefer using that instead in all cases whenever possible.

  • Related