Cuando busco en Internet optimizaciones / mejores prácticas react-native ( especialmente para FlatLists que a menudo son codiciosos ), siempre encuentro el consejo de no usar las funciones de flecha <Component onPress={() => ... } .
Ejemplo 1: https://reactnative.dev/docs/optimizing-flatlist-configuration#avoid-anonymous-function-on-renderitem :
Mueva la función renderItem al exterior de la función render, para que no se vuelva a crear cada vez que se llame a la función render. (...)
Ejemplo 2: https://blog.codemagic.io/improve-react-native-app-performance/ :
Evite las funciones de flecha: las funciones de flecha son un culpable común de los renderizados derrochadores. No use funciones de flecha como devoluciones de llamada en sus funciones para representar vistas (...)
Ejemplo 3: https://medium.com/wix-engineering/dealing-with-performance-issues-in-react-native-b181d0012cfa :
Las funciones de flecha son otro sospechoso habitual de renderizaciones derrochadoras. No use funciones de flecha como devoluciones de llamada (como hacer clic/tocar) en sus funciones de representación (...)
Entiendo que se recomienda no usar la función de flecha (especialmente en el botón onPress y FlatList ), y colocar los componentes fuera del renderizado si es posible.
Ejemplo de buenas prácticas:
const IndexScreen = () => { const onPress = () => console.log('PRESS, change state, etc...') return ( <> <Button onPress={onPress} /> <FlatList ... renderItem={renderItem} ListFooterComponent={renderFooter} /> </> ) } const renderItem = ({ item: data }) => <Item data={data} ... /> const renderFooter = () => <Footer ... /> export default IndexScreenPero, a menudo, tengo otras propiedades para integrar en mis componentes secundarios. Por lo tanto, la función de flecha es obligatoria:
const IndexScreen = () => { const otherData = ...(usually it comes from a useContext())... <FlatList ... renderItem={({ item: data }) => renderItem(data, otherData)} /> } const renderItem = (data, otherData) => <Item data={data} otherData={otherData} /> export default IndexScreen En esta última situación, ¿se siguen las buenas prácticas a pesar de la presencia de una función de flecha? En resumen, si otherData (por simplicidad), ¿son estas dos situaciones estrictamente idénticas y se siguen las buenas prácticas?
Situación 1:
const IndexScreen = () => { return ( <FlatList ... renderItem={renderItem} /> ) } const renderItem = ({ item: data }) => <Item data={data} ... /> export default IndexScreen=== Situación 2 ?
const IndexScreen = () => { return ( <FlatList ... renderItem={({ item: data }) => renderItem(data)} /> ) } const renderItem = (data) => <Item data={data} ... /> export default IndexScreenLa respuesta no tiene nada que ver con las funciones de flecha, sino más bien con comprender la igualdad de referencia por qué reaccionar podría decidir volver a representar un componente.
Puede usar useCallback para envolver su función. Esto hará que la referencia a renderItem solo se actualice cuando se actualice una de sus dependencias de devolución de llamada.
const renderItem = useCallback(()=>{ ... }, [otherdata]);La primera situación es ideal, porque cuando se ejecuta el código de su aplicación, solo se creará una función renderItem . En la segunda situación, incluso si no tiene otros Props, no está siguiendo la buena práctica porque se crea una nueva función cada renderizado en esta línea
renderItem={({ item: data }) => renderItem(data)}Por lo tanto, hacer que FlatList se reproduzca cada vez.
Para solucionarlo, debe memorizar la función que pasa en el accesorio renderItem con useCallback
const renderItem = useCallback(({ item: data }) => { return (<Item data={data} />) }, []); ... <FlatList ... renderItem={renderItem} /> por lo tanto, la versión memorizada se creará solo una vez cuando se monte el componente. Y, si necesita inyectar más datos en la función de renderizado, defina esos datos como una dependencia del useCallback para crear la función solo cuando esos datos cambien, reduciendo los renderizados en el árbol.
const renderItem = useCallback(({ item: data }) => { return (<Item data={data} otherData={otherData} />) }, [otherData]);para mí, como se señaló anteriormente en otras respuestas, el problema se debe principalmente al hecho de que si usa funciones de flecha dentro del código, la función se redefine cada vez. Además, esta forma de definir una función hace que esta función no tenga nombre, por lo que es más difícil de rastrear durante la depuración: en el seguimiento de la pila de errores, puede ver el nombre de una función con nombre directamente en el código.
const renderItem = useCallback( function renderItemFunction ({ item: data }) { return (<Item data={data} otherData={otherData} />) }, [otherData]); de esta manera, en el seguimiento de la pila de errores, debería ver la indicación renderItemFunction