https://github.com/urian121/react-native-guia-completa-componentes
Guía completa de componentes en React Native 📱. Aprende a usar y personalizar los principales componentes con ejemplos prácticos y buenas prácticas. Ideal para principiantes y desarrolladores avanzados. 🚀
https://github.com/urian121/react-native-guia-completa-componentes
frontend guia-react-native javascript mobile-development react react-native react-native-components react-native-guide react-native-tutorial react-native-ui reactnative ui-components ui-components-react-native
Last synced: about 2 months ago
JSON representation
Guía completa de componentes en React Native 📱. Aprende a usar y personalizar los principales componentes con ejemplos prácticos y buenas prácticas. Ideal para principiantes y desarrolladores avanzados. 🚀
- Host: GitHub
- URL: https://github.com/urian121/react-native-guia-completa-componentes
- Owner: urian121
- Created: 2025-03-13T22:24:46.000Z (2 months ago)
- Default Branch: master
- Last Pushed: 2025-03-14T02:33:05.000Z (2 months ago)
- Last Synced: 2025-03-14T03:23:38.987Z (2 months ago)
- Topics: frontend, guia-react-native, javascript, mobile-development, react, react-native, react-native-components, react-native-guide, react-native-tutorial, react-native-ui, reactnative, ui-components, ui-components-react-native
- Homepage:
- Size: 71.3 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# 📖 Guía Completa de Componentes en React Native
Guía completa de componentes en React Native 📱. Aprende a usar y personalizar los principales componentes con ejemplos prácticos y buenas prácticas. 🚀
## 1️⃣ Instalación y Configuración
Si aún no tienes un entorno de desarrollo configurado, puedes instalar **React Native CLI** o usar **Expo** (***recomendado por React***):
### Instalación con Expo
```bash
npx create-expo-app MiApp
cd MiApp
npx expo start
```### Instalación con React Native CLI
```bash
npx react-native init MiApp
cd MiApp
npx react-native start
```## 2️⃣ Primer Componente
Un componente funcional básico en **React Native** se define así:
```jsx
import React from 'react';
import { Text, View } from 'react-native';const MiComponente = () => {
return (
¡Hola, React Native!
);
};export default MiComponente;
```📌 **Explicación:**
- ``: Similar a un `` en HTML.
- ``: Se usa para mostrar texto.## 3️⃣ Componentes Básicos
### 🟢 View (Contenedor)
**`View`**: Es el componente más básico sobre el que heredan la mayoría de los demás componentes. Lo podríamos comparar como un `` de HTML.```jsx
Este es un contenedor
```
### 📌 Importante
> [!IMPORTANT]
> En **React** y **React Native**, las dobles llaves (`{{ }}`) indican que estás pasando un **objeto** en **JSX**.
> - La primera `{ }` permite escribir una expresión de **JavaScript** dentro de **JSX**.
> - La segunda `{ }` contiene el objeto con los estilos en formato **clave-valor**.
>
> 📌 Esto es necesario porque los estilos en React se definen como objetos de JavaScript en lugar de cadenas CSS.#### Crear un contenedor fácilmente usando `View`
Este código define un componente `Container` que usa `View` para envolver y aplicar estilos a sus hijos.
En `App`, el `Container` se reutiliza para mostrar un `Text` dentro de un fondo estilizado.```jsx
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';const Container = ({ children }) => {
return {children};
};const styles = StyleSheet.create({
container: {
flex: 1,
padding: 20,
backgroundColor: '#f5f5f5',
},
});export default function App() {
return (
Hola, esto está dentro del contenedor
);
}
```### 🔤 Text (Texto)
**`Text`**: Componente para mostrar textos.```jsx
Texto en React Native
```
### 🔘 Button (Botón)
**`Button`**: Sirve para crear botones interactivos básicos con una apariencia estándar según la plataforma (iOS o Android).```jsx
import { Button } from 'react-native';alert('¡Clic!')}
color="#841584"
/>
```### 🎛️ TextInput (Caja de Texto)
**`TextInput`**: Componente que proporciona un espacio al usuario para que pueda ingresar texto por medio del teclado de su dispositivo.```jsx
import React, { useState } from 'react';
import { TextInput } from 'react-native';const InputExample = () => {
const [texto, setTexto] = useState('');
return (
);
};
```### 📸 Image (Imagen)
**`Image`**: Componente que sirve para mostrar imágenes```jsx
import React, { useState } from 'react';
import { Image } from 'react-native';// Imagen desde URL
// Imagen local
```
### 📱 Componente SafeAreaView
Se usa para asegurarse de que el contenido de la pantalla no se superponga con áreas seguras del dispositivo, como el **`notch`** en iPhones o la barra de navegación en **`Android`**.#### Cómo funciona 🤔
- `SafeAreaView` ajusta automáticamente su padding para evitar que el contenido quede oculto detrás de áreas no seguras.
Funciona mejor en **iOS**, pero en **Android** no tiene efecto a menos que uses SafeAreaProvider de la librería `react-native-safe-area-context`.```jsx
import React from 'react';
import { SafeAreaView, Text, StyleSheet } from 'react-native';export default function App() {
return (
Hola, esto está dentro de SafeAreaView
);
}const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f5f5f5',
},
});
```#### 📝 Mejor soporte en Android
En **Android**, para un mejor comportamiento, usa `SafeAreaProvider` de `react-native-safe-area-context`:1. Instala la librería
`npm install react-native-safe-area-context`2. Implementación con SafeAreaProvider
```jsx
import React from 'react';
import { SafeAreaView, Text, StyleSheet } from 'react-native';
import { SafeAreaProvider } from 'react-native-safe-area-context';export default function App() {
return (
Contenido seguro en iOS y Android
);
}const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f5f5f5',
},
});
```
✅ Con esta configuración, el `SafeAreaView` funciona bien en **iOS** y **Android**.### 📜 ScrollView (Vista Desplazable)
**`ScrollView`**: Componente permite establecer un contenedor en el que se podrán almacenar varios componentes que se pueden ir desplazando en la pantalla.```jsx
import React, { useState } from 'react';
import { ScrollView, View, Text, StyleSheet } from 'react-native';const ScrollViewExample = () => {
return (
{/* Contenido que puede desplazarse verticalmente */}
Sección 1
Sección 2
Sección 3
);
};// ScrollView horizontal
const HorizontalScrollExample = () => {
return (
);
};
```### 🔄 ActivityIndicator (Indicador de Carga)
**`ActivityIndicator`**: Muestra un indicador de carga circular animado.
Se utiliza para indicar a los usuarios que una operación está en proceso, como cuando se están cargando datos de una `API`, procesando información o realizando cualquier tarea que requiera tiempo.```jsx
import React, { useState } from 'react';
import { ActivityIndicator, View } from 'react-native';const LoadingIndicator = () => {
return (
);
};
```### 📱 TouchableOpacity (Área Táctil)
**`TouchableOpacity`**: Crea áreas táctiles que responden al toque del usuario con un efecto de opacidad.
Cuando el usuario presiona el elemento, este se vuelve ligeramente transparente (reduce su opacidad) para proporcionar retroalimentación visual.```jsx
import React, { useState } from 'react';
import { TouchableOpacity, Text } from 'react-native';const TouchableExample = () => {
return (
alert('Tocado!')}
>
Botón Personalizado
);
};
```## 4️⃣ Componentes con Estado (`useState`)
Para manejar datos dentro de un componente usamos `useState`:```jsx
import React, { useState } from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';const Contador = () => {
const [contador, setContador] = useState(0);
return (
Contador: {contador}
setContador(contador + 1)} />
setContador(contador - 1)} />
setContador(0)} />
);
};const styles = StyleSheet.create({
container: {
padding: 20,
alignItems: 'center',
},
contador: {
fontSize: 24,
marginBottom: 20,
},
buttonRow: {
flexDirection: 'row',
justifyContent: 'space-between',
width: '100%',
marginBottom: 10,
},
});export default Contador;
```📌 **Explicación:**
- `useState(0)`: Crea una variable de estado (contador) con valor inicial `0`.
- `setContador(contador + 1)`: Actualiza el estado al hacer clic.## 5️⃣ Estilos en React Native
Se pueden definir estilos de dos maneras:### 1️⃣ Estilos en línea
```jsx
Texto Azul
```
### 2️⃣ Estilos con StyleSheet (Recomendado)
**`StyleSheet`**: Componente en el que añadiremos los estilos del componente.```jsx
import React, { useState } from 'react';
import { StyleSheet, View, Text } from 'react-native';const MiComponente = () => {
return (
Título Principal
Subtítulo
);
};const styles = StyleSheet.create({
container: {
flex: 1,
padding: 20,
backgroundColor: '#f5f5f5',
},
titulo: {
color: 'red',
fontSize: 24,
fontWeight: 'bold',
marginBottom: 10,
},
subtitulo: {
color: '#333',
fontSize: 18,
}
});export default MiComponente;
```### 3️⃣ Combinando estilos
```jsx
Este texto combina estilos
```
## 6️⃣ Diseño con Flexbox
**React Native** utiliza Flexbox para el diseño:```jsx
import React, { useState } from 'react';
import { View, StyleSheet } from 'react-native';const FlexboxExample = () => {
return (
);
};const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row', // 'column', 'row', 'column-reverse', 'row-reverse'
justifyContent: 'space-between', // 'flex-start', 'flex-end', 'center', 'space-around'
alignItems: 'center', // 'flex-start', 'flex-end', 'stretch'
padding: 20,
},
box1: { width: 50, height: 50, backgroundColor: 'red' },
box2: { width: 50, height: 50, backgroundColor: 'green' },
box3: { width: 50, height: 50, backgroundColor: 'blue' },
});
```## 7️⃣ Listas y Scroll
### FlatList (Para listas largas)
Renderiza listas de datos extensas de forma eficiente, cargando solo los elementos visibles en pantalla. Es ideal para mostrar grandes colecciones de datos con buen rendimiento.```jsx
import React, { useState } from 'react';
import { FlatList, Text, View, StyleSheet } from 'react-native';const datos = [
{ id: '1', nombre: 'Juan' },
{ id: '2', nombre: 'Ana' },
{ id: '3', nombre: 'Carlos' },
{ id: '4', nombre: 'María' },
// ... más datos
];const Lista = () => (
item.id}
renderItem={({ item }) => (
{item.nombre}
)}
ItemSeparatorComponent={() => }
/>
);const styles = StyleSheet.create({
item: {
padding: 15,
backgroundColor: 'white',
},
nombre: {
fontSize: 16,
},
separator: {
height: 1,
backgroundColor: '#eeeeee',
},
});export default Lista;
```### 📜 SectionList (Para listas con secciones)
Muestra datos organizados en secciones con encabezados. Es similar a FlatList pero permite agrupar elementos relacionados bajo títulos de sección, ideal para datos categorizados como contactos por inicial, productos por categoría o ajustes agrupados por función.```jsx
import React, { useState } from 'react';
import { SectionList, Text, View, StyleSheet } from 'react-native';const datos = [
{
title: 'Frutas',
data: ['Manzana', 'Banana', 'Naranja'],
},
{
title: 'Verduras',
data: ['Zanahoria', 'Brócoli', 'Espinaca'],
},
];const SectionListExample = () => (
item + index}
renderItem={({ item }) => (
{item}
)}
renderSectionHeader={({ section: { title } }) => (
{title}
)}
/>
);const styles = StyleSheet.create({
item: {
padding: 10,
backgroundColor: 'white',
},
itemText: {
fontSize: 16,
},
sectionHeader: {
padding: 10,
backgroundColor: '#f0f0f0',
},
sectionTitle: {
fontSize: 18,
fontWeight: 'bold',
},
});
```## 8️⃣ Uso de API con `fetch`
Para obtener datos de una API usamos `fetch`:```jsx
import React, { useEffect, useState } from 'react';
import { View, Text, FlatList, StyleSheet, ActivityIndicator } from 'react-native';const ApiExample = () => {
const [data, setData] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/users');
if (!response.ok) {
throw new Error('La respuesta de la red no fue satisfactoria');
}
const json = await response.json();
setData(json);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
};fetchData();
}, []);if (loading) {
return (
);
}if (error) {
return (
Error: {error}
);
}return (
item.id.toString()}
renderItem={({ item }) => (
{item.name}
{item.email}
)}
/>
);
};const styles = StyleSheet.create({
centered: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
error: {
color: 'red',
fontSize: 18,
},
userItem: {
padding: 15,
borderBottomWidth: 1,
borderBottomColor: '#eee',
},
userName: {
fontSize: 18,
fontWeight: 'bold',
},
userEmail: {
fontSize: 14,
color: '#666',
},
});export default ApiExample;
```## 9️⃣ Navegación entre Pantallas
Para la navegación, instala `React Navigation`:```bash
npm install @react-navigation/native
npx expo install react-native-screens react-native-safe-area-context
npm install @react-navigation/native-stack
```### Ejemplo de Navegación Básica
```jsx
import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { Button, Text, View } from 'react-native';// Pantalla de Inicio
const HomeScreen = ({ navigation }) => {
return (
Pantalla de Inicio
navigation.navigate('Details', { itemId: 86, title: 'Mi Título' })}
/>
);
};// Pantalla de Detalles
const DetailsScreen = ({ route, navigation }) => {
const { itemId, title } = route.params;
return (
Pantalla de Detalles
itemId: {itemId}
title: {title}
navigation.goBack()} />
);
};const Stack = createNativeStackNavigator();
const App = () => {
return (
({ title: route.params.title })}
/>
);
};export default App;
```## 🔟 Hooks Comunes
### `useEffect` (Efectos Secundarios)
**`useEffect`** es un hook de efectos secundarios que permite ejecutar código en diferentes momentos del ciclo de vida de un componente.
Se usa comúnmente para **cargar datos, suscribirse a eventos, manipular el DOM, o ejecutar lógica después de renderizar**.```jsx
import React, { useState, useEffect } from 'react';
import { Text, View } from 'react-native';const Timer = () => {
const [seconds, setSeconds] = useState(0);useEffect(() => {
const interval = setInterval(() => {
setSeconds(prevSeconds => prevSeconds + 1);
}, 1000);
// Función de limpieza
return () => clearInterval(interval);
}, []); // Array vacío = ejecutar solo al montarreturn (
Segundos: {seconds}
);
};
```### `useContext` (Contexto Global)
**`useContext`**: permite acceder a un contexto global en cualquier parte de la aplicación sin necesidad de pasar `props` manualmente.
Es útil para manejar estados globales como autenticación, temas, idiomas, etc.```jsx
import React, { createContext, useContext, useState } from 'react';
import { View, Text, Button } from 'react-native';// Crear el contexto
const TemaContext = createContext();// Proveedor de contexto
const TemaProvider = ({ children }) => {
const [tema, setTema] = useState('claro');
const cambiarTema = () => {
setTema(temaActual => temaActual === 'claro' ? 'oscuro' : 'claro');
};
return (
{children}
);
};// Componente que consume el contexto
const ComponenteTematizado = () => {
const { tema, cambiarTema } = useContext(TemaContext);
return (
Tema actual: {tema}
);
};// Uso en la app
const App = () => {
return (
);
};
```## 1️⃣1️⃣ Manejo de Formularios
```jsx
import React, { useState } from 'react';
import { View, TextInput, Button, Text, StyleSheet, Alert } from 'react-native';const FormularioExample = () => {
const [formState, setFormState] = useState({
nombre: '',
email: '',
password: ''
});
const [errors, setErrors] = useState({});
const handleChange = (field, value) => {
setFormState({
...formState,
[field]: value
});
};
const validarFormulario = () => {
let tempErrors = {};
if (!formState.nombre) tempErrors.nombre = "El nombre es obligatorio";
if (!formState.email) tempErrors.email = "El email es obligatorio";
else if (!/\S+@\S+\.\S+/.test(formState.email)) {
tempErrors.email = "Email inválido";
}
if (!formState.password) tempErrors.password = "La contraseña es obligatoria";
else if (formState.password.length < 6) {
tempErrors.password = "La contraseña debe tener al menos 6 caracteres";
}
setErrors(tempErrors);
return Object.keys(tempErrors).length === 0;
};
const handleSubmit = () => {
if (validarFormulario()) {
// Aquí enviarías los datos al servidor
Alert.alert("Éxito", "Formulario enviado correctamente");
console.log("Datos del formulario:", formState);
}
};
return (
Nombre:
handleChange('nombre', text)}
placeholder="Escribe tu nombre"
/>
{errors.nombre && {errors.nombre}}
Email:
handleChange('email', text)}
placeholder="[email protected]"
keyboardType="email-address"
autoCapitalize="none"
/>
{errors.email && {errors.email}}
Contraseña:
handleChange('password', text)}
placeholder="********"
secureTextEntry
/>
{errors.password && {errors.password}}
);
};const styles = StyleSheet.create({
form: {
padding: 20,
},
label: {
fontSize: 16,
marginBottom: 5,
fontWeight: 'bold',
},
input: {
borderWidth: 1,
borderColor: '#ddd',
padding: 10,
borderRadius: 5,
marginBottom: 15,
},
errorInput: {
borderColor: 'red',
},
errorText: {
color: 'red',
fontSize: 12,
marginTop: -10,
marginBottom: 10,
}
});export default FormularioExample;
```### 📋 Formulario con `react-hook-form` en React Native
Esta librería facilita mucho la validación y gestión de formularios.```jsx
import React from 'react';
import { View, Text, TextInput, Button, StyleSheet, ScrollView, Alert } from 'react-native';
import { useForm, Controller } from 'react-hook-form';const FormularioEjemplo = () => {
const { control, handleSubmit, formState: { errors }, reset } = useForm({
defaultValues: {
nombre: '',
correo: '',
telefono: '',
edad: '',
mensaje: ''
}
});const onSubmit = (data) => {
// Aquí procesarías el envío del formulario
console.log('Datos del formulario:', data);
// Mostrar los datos enviados
Alert.alert(
'Formulario Enviado',
`Nombre: ${data.nombre}\nCorreo: ${data.correo}\nTeléfono: ${data.telefono}\nEdad: ${data.edad}\nMensaje: ${data.mensaje}`,
[{ text: 'OK', onPress: () => reset() }]
);
};return (
Formulario de Contacto
{/* Control de Nombre */}
Nombre:
(
)}
name="nombre"
/>
{errors.nombre && {errors.nombre.message}}
{/* Control de Correo */}
Correo electrónico:
(
)}
name="correo"
/>
{errors.correo && {errors.correo.message}}
{/* Control de Teléfono */}
Teléfono:
(
)}
name="telefono"
/>
{errors.telefono && {errors.telefono.message}}
{/* Control de Edad */}
Edad:
parseInt(value) >= 18 || 'Debes ser mayor de edad'
}}
render={({ field: { onChange, onBlur, value } }) => (
)}
name="edad"
/>
{errors.edad && {errors.edad.message}}
{/* Control de Mensaje */}
Mensaje:
(
)}
name="mensaje"
/>
{errors.mensaje && {errors.mensaje.message}}
);
};const styles = StyleSheet.create({
container: {
padding: 20,
backgroundColor: '#f5f5f5',
},
title: {
fontSize: 24,
fontWeight: 'bold',
marginBottom: 20,
textAlign: 'center',
},
label: {
fontSize: 16,
marginBottom: 5,
fontWeight: '500',
},
input: {
borderWidth: 1,
borderColor: '#ddd',
borderRadius: 4,
padding: 10,
marginBottom: 12,
backgroundColor: '#fff',
},
textArea: {
height: 100,
textAlignVertical: 'top',
},
errorText: {
color: 'red',
fontSize: 12,
marginBottom: 10,
marginTop: -8,
},
});export default FormularioEjemplo;
```Este formulario en **React Native** usa `react-hook-form` para gestionar y validar los campos de entrada.
`Controller` maneja cada `TextInput`, aplicando reglas como requerimientos, validaciones de formato y longitud.
Los errores se muestran dinámicamente debajo de cada campo.
Al enviarlo, los datos se muestran en una alerta y el formulario se reinicia con `reset()`.
También utiliza `ScrollView` para evitar problemas de desplazamiento en pantallas pequeñas.## 1️⃣2️⃣ Mejores Prácticas
### Separar Lógica y Presentación
```jsx
// Component/UserProfile/index.js (Componente contenedor - lógica)
import React, { useState, useEffect } from 'react';
import UserProfileView from './UserProfileView';const UserProfile = ({ userId }) => {
const [userData, setUserData] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
// Obtener datos del usuario
fetch(`https://api.example.com/users/${userId}`)
.then(response => response.json())
.then(data => {
setUserData(data);
setLoading(false);
});
}, [userId]);
const handleUpdateName = (newName) => {
// Lógica para actualizar nombre
};
return (
);
};// Component/UserProfile/UserProfileView.js (Componente de presentación)
import React from 'react';
import { View, Text, ActivityIndicator, Button, TextInput } from 'react-native';const UserProfileView = ({ userData, loading, onUpdateName }) => {
if (loading) {
return ;
}
return (
Nombre: {userData.name}
Email: {userData.email}
{/* Resto del UI */}
);
};
```### Personalizar Componentes Reutilizables
```jsx
// Components/CustomButton.js
import React from 'react';
import { TouchableOpacity, Text, StyleSheet } from 'react-native';const CustomButton = ({
title,
onPress,
type = 'primary', // 'primary', 'secondary', 'outline'
size = 'medium', // 'small', 'medium', 'large'
disabled = false,
style = {}
}) => {
return (
{title}
);
};const styles = StyleSheet.create({
button: {
borderRadius: 8,
justifyContent: 'center',
alignItems: 'center',
},
primary: {
backgroundColor: '#2196F3',
},
secondary: {
backgroundColor: '#FF9800',
},
outline: {
backgroundColor: 'transparent',
borderWidth: 1,
borderColor: '#2196F3',
},
small: {
paddingVertical: 6,
paddingHorizontal: 12,
},
medium: {
paddingVertical: 10,
paddingHorizontal: 16,
},
large: {
paddingVertical: 14,
paddingHorizontal: 24,
},
disabled: {
backgroundColor: '#CCCCCC',
borderColor: '#CCCCCC',
},
text: {
fontWeight: 'bold',
},
primaryText: {
color: 'white',
},
secondaryText: {
color: 'white',
},
outlineText: {
color: '#2196F3',
},
disabledText: {
color: '#888888',
},
});export default CustomButton;
// Uso del componente personalizado
import CustomButton from './Components/CustomButton';const Screen = () => {
return (
alert('Primario!')}
/>
alert('Secundario!')}
/>
alert('Outline!')}
/>
alert('No se ejecutará')}
/>
);
};
```## 1️⃣3️⃣ Depuración y Herramientas
### Console.log para debugging:
```jsx
const MiComponente = () => {
const datos = { nombre: 'Juan', edad: 30 };
console.log('Datos actuales:', datos);
console.warn('Advertencia importante');
console.error('Error crítico');
return ...;
};
```### Uso de React DevTools:
1. Instala React DevTools:
```bash
npm install -g react-devtools
```2. Ejecuta en otra terminal:
```bash
react-devtools
```3. Conecta tu aplicación (sigue las instrucciones en pantalla)
## 1️⃣4️⃣ Optimizaciones de Rendimiento
### Uso de `React.memo` para componentes puros:
```jsx
import React, { memo } from 'react';
import { Text } from 'react-native';const MiComponente = memo(({ texto }) => {
console.log('Renderizando MiComponente');
return {texto};
});export default MiComponente;
```### `useMemo` para cálculos costosos:
**`useMemo`**: memoriza valores computados para evitar cálculos innecesarios en cada render.
Se usa cuando tienes funciones costosas o cálculos que no deberían ejecutarse si sus dependencias no han cambiado.```jsx
import React, { useMemo } from 'react';
import { View, Text } from 'react-native';const ListaFiltrada = ({ items, filtro }) => {
const itemsFiltrados = useMemo(() => {
console.log('Calculando filtro...');
return items.filter(item => item.includes(filtro));
}, [items, filtro]); // Solo recalcula si items o filtro cambian
return (
{itemsFiltrados.map(item => (
{item}
))}
);
};
```### `useCallback` para funciones:
Sirve para memorizar funciones, evitando que se vuelvan a crear en cada render. Esto mejora el rendimiento al evitar que componentes hijos innecesariamente se vuelvan a renderizar.```jsx
import React, { useState, useCallback } from 'react';
import { View, Button } from 'react-native';const Contador = () => {
const [contador, setContador] = useState(0);
// useCallback evita recrear la función en cada renderizado
const incrementar = useCallback(() => {
setContador(c => c + 1);
}, []); // Array vacío = no depende de ningún valor
return (
);
};
```