Diseño de la lista de compras con React Native y Expo .
git clone https://github.com/RafaelR4mos/challenge-react-native-shop-list.git package.json npm installnpm run startUse la biblioteca de iconos para la versión RN.
npm install phosphor-react-nativeUso de iconos:
import { Basket } from 'phosphor-react-native'
export function Componente() {
return (
<Basket
size={32}
color="#FFFFFF"
weight='bold'
/>
)
}
Componentes estilizados y uso de temas. La mayor diferencia para la versión web está en la escritura y notificación de la versión RN
//styles.ts
import 'styled-components/native' ;
export const Container = styled . View `
color: red;
` ; //tipagem
import 'styled-components/native' ;
import theme from '../theme' ; //caminho do tema
//importante usar o '/native' aqui também.
declare module 'styled-components/native' {
type ThemeType = typeof theme ;
export interface DefaultTheme extends ThemeType { }
} attrs Para que sea posible consumir el tema de la aplicación y no tener que estilo en el archivo .tsx en sí, podemos usar en styles.ts el siguiente código:
//Aqui mudamos os atributos 'size' e 'color' através do arquivo de estilização
export const BackIcon = styled ( CaretLeft ) . attrs ( ( { theme } ) => ( {
size : 32 ,
color : theme . COLORS . WHITE ,
} ) ) `` ;type en TypeScriptSi creamos un componente personalizado y también es necesario extender la escritura del componente nativo, podemos usar el código como base:
//Importa tipagem do touchable opacity que vem do RN
import { TouchableOpacityProps } from 'react-native' ;
//Com o caractere '&' adiciona os tipos nativos + o que for definido entre chaves
type GroupCardProps = TouchableOpacityProps & {
title : string ;
} ; Cuando hay un uso de muchas variables como theme , type , variant y otras en un componente, solo puede ser que el ayudante de componentes css estilo contribuya a simplificar la sintaxis.
import styled , { css } from 'styled-components/native' ;
//Com isso `theme` não precisa ser desestruturado em todas propriedades.
export const NumbersOfPlayers = styled . Text `
${ ( { theme } ) => css `
color: ${ theme . COLORS . GRAY_200 } ;
font-family: ${ theme . FONT_FAMILY . BOLD } ;
font-size: ${ theme . FONT_SIZE . SM } px;
` } ;
` ;npm install @react-navigation/nativeexpo npx expo install react-native-screens react-native-safe-area-contextnpm install @react-navigation/native-stackcontexto de rutas y rotas : routes/app.routes.tsx
import { createNativeStackNavigator } from '@react-navigation/native-stack' ;
import { MyLists } from '../screens/MyyList' ;
const { Navigator , Screen } = createNativeStackNavigator ( ) ;
//Navigator --> Envolve as rotas
//Screen --> Rota individual com nome e apontando para componente
export function AppRoutes ( ) {
return (
< Navigator screenOptions = { { headerShown : false } } >
< Screen
name = "myLists"
component = { MyLists }
/>
</ Navigator >
) ;
} index.tsx
import { NavigationContainer } from '@react-navigation/native' ;
import { useTheme } from 'styled-components/native' ;
import { AppRoutes } from './app.routes' ;
import { View } from 'react-native' ;
export function Routes ( ) {
const { COLORS } = useTheme ( ) ;
//NavigationContainer --> Fornece o contexto de navegação para o app.
// * A estilização da view remove o glitch effect ao trocar de página.
return (
< View style = { { flex : 1 , backgroundColor : COLORS . GRAY_600 } } >
< NavigationContainer >
< AppRoutes />
</ NavigationContainer >
</ View >
) ;
} @types/ Es interesante saber qué rutas existen en nuestra aplicación y especialmente qué params se esperan en cada una de las rutas.
Crear un archivo navigation.d.ts
Reescribir el módulo que escribe en el archivo
export declare global {
namespace ReactNavigation {
interface RootParamList {
myLists : undefined ;
newList : undefined ;
list : {
listName : string ;
} ;
}
}
} A veces necesitamos intercambiar información entre las páginas de nuestra aplicación, para esto, podemos usar react-navigation de Lib y sus ganchos
useNavigation() import { useNavigation } from '@react-navigation/native' ; const navigation = useNavigation ( ) ;navigate navigation . navigate ( 'route' , { state } ) ; Es importante usar el gancho useRoute , que también proviene de react-navigation . En esto es posible interrumpir los parámetros desde route.params Parámetros ideiales también es tiar ¿Cuáles son estos parámetros con el "como" + tipage
const route = useRoute ( ) ;
const { param } = route . params as RouteParams ; useFocusEffect para enfocar en la página useFocusEffect es bastante similar a useEffect , sin embargo, se activa cada vez que la página recibe enfoque, es decir, además de la primera carga, se invoca si se produce una navegación a la página
Importar:
import { useFocusEffect } from '@react-navigation/native' ;Usar:
useFocusEffect (
useCallback ( ( ) => {
fetchLists ( ) ;
} , [ ] )
) ;
useCallBackse usa juntos para evitar disparar una representación innecesaria, lo que puede ayudar con el rendimiento de la aplicación.
Similar a la ubicación del navegador. Puede ayudar a resolver problemas de prop-drilling a medida que centraliza la información en un solo lugar.
Instalación:
npx expo instal @react-native-async-storage/async-storage
La dinámica de tratar con AsyncStorage , similar a LocalStorage, pero asíncrono es diferente y hay un patrón que se puede usar.
Creación de una carpeta solo para este storage
Creación de un archivo storageConfig.ts para definir claves de almacenamiento
Con esto, garantizamos un mejor mantenimiento en las claves de los elementos guardados en AsyncStorage
const LIST_COLLECTION = '@shop-list:lists' ;
const ITEM_COLLECTION = '@shop-list:items' ;
export { LIST_COLLECTION , ITEM_COLLECTION } ;Ejemplo: jugador
Archivo:
| -Lista | ListCreate.ts | listDelete.ts | listgetall.ts | listgetsingle.ts
import AsyncStorage from '@react-native-async-storage/async-storage' ;
import { LIST_COLLECTION } from '../storageConfig' ;
import { ShoppingList } from '../../screens/Lists' ;
import { listsGetAll } from './listGetAll' ;
import { AppError } from '../../utils/AppError' ;
export async function listCreate ( newList : ShoppingList ) {
try {
const storedLists = await listsGetAll ( ) ;
const listAlreadyExists = storedLists
. map ( ( item : ShoppingList ) => item . title )
. includes ( newList . title ) ;
if ( listAlreadyExists ) {
throw new AppError ( 'Já existe uma lista com este nome.' ) ;
}
const newStorage = JSON . stringify ( [ ... storedLists , newList ] ) ;
await AsyncStorage . setItem ( LIST_COLLECTION , newStorage ) ;
console . log ( storedLists ) ;
} catch ( error ) {
throw error ;
}
}useRef() para tratar con elementos Podemos usar el Hook Useref () para acceder a la referencia de un elemento y, por lo tanto, tratar con focus() , blur() , entre otros.
Ejemplo: al enviar un formulario, podemos usar blur() en el elemento de entrada, después de todo, el usuario ya ha ingresado lo necesario, por lo que el efecto desfoque puede finalizar el teclado abierto y eliminar el enfoque a la entrada.
//Criação da referência de vinculação
const newListNameInputRef = useRef < TextInput > ( null ) ;
function handleSubmit ( ) {
///...
//Desfoca o elemento
newListNameInputRef . current ?. blur ( ) ;
}
//IMPORTANTE adicionar o `ref` ao elemento, caso seja um componente é necessário enviar via prop.
return (
< View >
< Input
inputRef = { newListNameInputRef }
onChangeText = { setNewListName }
value = { newListName }
placeholder = "Nome da sua lista"
autoCorrect = { false }
onSubmitEditing = { handleAddList }
returnKeyType = "done"
/ >
< / View >
) ; Para que podamos distinguir un error genérico/desconocido proporcionado por un throw y un error reconocido por nuestra aplicación, podemos crear una clase con un atributo message e instanciar esta clase, para que podamos recopilar instaceof <classe> dentro del bloque catch .
Ejemplo:
export class AppError {
message : string ;
constructor ( message : string ) {
this . message = message ;
}
} throw new AppError ( 'Estas lista já esta adicionada!' ) ; catch ( error ) {
if ( error instanceof AppError ) {
Alert . alert ( 'Nova lista' , error . message ) ;
} else {
Alert . alert ( 'Nova lista' , 'Não foi possível adicionar' ) ;
console . error ( error ) ;
}
}Por: ¿Rafael Ramos?