¿Cuál es la forma más eficiente de evitar una función en línea en un bucle?
const SomeComponent = () => { const handler = (idx) => console.log(idx); return (<> [...Array(100)].map((_, index) => ( <div onClick=(() => handler(index))>Click me {index}</div> </>); }
Supongo que esto es un poco de ingeniería excesiva
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> </>); }
Los "problemas" en los que estaba pensando eran/son:
Creo que está perfectamente bien. Es muy poco probable que tenga ningún impacto en el rendimiento. Pero si es algo que le preocupa, dado que el index
está dentro del alcance de la devolución de llamada .map
, la única otra opción que se me ocurre es que el controlador examine el DOM que lo rodea para obtener el índice:
<div onClick={handler}>Click me {index}</div>
const handler = (e) => { const div = e.currentTarget; const index = [...div.parentElement.children].indexOf(div); console.log(index); };
Pero usar {() => handler(index)}
es un estilo mucho más parecido a React, y es mucho más fácil de leer y entender; prefiero usar eso en todos los casos siempre que sea posible.
Siempre que el handler
no sea demasiado complicado, también puede definirlo dentro del map
y luego referirse a él directamente en onClick
. Para mí personalmente, eso incluso deja más claro lo que va a pasar, porque no tengo que hacer el salto mental de una función a la siguiente para averiguarlo.
demostración de trabajo:
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>
PD: tuve que hacer algunos pequeños cambios porque su código no era sintácticamente correcto.