Conception de la liste d'achat avec React Native et Expo .
git clone https://github.com/RafaelR4mos/challenge-react-native-shop-list.git package.json npm installnpm run startUtilisez la bibliothèque d'icônes pour la version RN.
npm install phosphor-react-nativeUtilisation des icônes:
import { Basket } from 'phosphor-react-native'
export function Componente() {
return (
<Basket
size={32}
color="#FFFFFF"
weight='bold'
/>
)
}
Composants stylisés et utilisation des thèmes. La plus grande différence pour la version Web est la frappe et la note de la version 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 Afin qu'il soit possible de consommer le thème de l'application et de ne pas avoir à styliser dans le fichier .tsx lui-même que nous pouvons utiliser dans styles.ts le code suivant:
//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 sur TypeScriptSi nous créons un composant personnalisé et qu'il est également nécessaire d'étendre le typage du composant natif, nous pouvons utiliser le code comme 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 ;
} ; Lorsqu'il y a une utilisation de nombreuses variables telles que theme , type , variant et autres dans un composant, il se peut que l'assistance css componotes stylisées contribue à simplifier la syntaxe.
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 des itinéraires et 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/ Il est intéressant de dire quels itinéraires existent dans notre application et surtout quels params sont attendus sur chacun des itinéraires
Créer un fichier de navigation.d.ts
Réécrivez le module Taping dans le fichier
export declare global {
namespace ReactNavigation {
interface RootParamList {
myLists : undefined ;
newList : undefined ;
list : {
listName : string ;
} ;
}
}
} Parfois, nous devons échanger des informations entre les pages de notre application, pour cela, nous pouvons utiliser Lib react-navigation et ses crochets
useNavigation() import { useNavigation } from '@react-navigation/native' ; const navigation = useNavigation ( ) ;navigate navigation . navigate ( 'route' , { state } ) ; Il est important d'utiliser le Hook useRoute , qui provient également de react-navigation . En cela, il est possible de perturber les paramètres de route.params Params Ideial est également en diadie quels sont ces paramètres avec le "AS" + Tipage
const route = useRoute ( ) ;
const { param } = route . params as RouteParams ; useFocusEffect pour se concentrer sur la page useFocusEffect est assez similaire à useEffect , mais il est activé chaque fois que la page reçoit une mise au point, c'est-à-dire en plus de la 1ère charge, elle est invoquée si une navigation se produit à la page
Importer:
import { useFocusEffect } from '@react-navigation/native' ;Utiliser:
useFocusEffect (
useCallback ( ( ) => {
fetchLists ( ) ;
} , [ ] )
) ;
useCallBackest utilisé ensemble pour éviter de licencier un rendu inutile, ce qui peut aider les performances de l'application.
Similaire à l'emplacement du navigateur. Il peut aider à résoudre des problèmes prop-drilling car il centralise les informations en un seul endroit.
Installation:
npx expo instal @react-native-async-storage/async-storage
La dynamique de la gestion de AsyncStorage , similaire à Localstorage, mais asynchrone est différent et il existe un modèle qui peut être utilisé.
Création d'un dossier uniquement pour ce storage
Création d'un fichier storageConfig.ts pour définir les clés de stockage
Avec cela, nous garantissons une meilleure maintenance dans les clés des éléments enregistrés dans AsyncStorage
const LIST_COLLECTION = '@shop-list:lists' ;
const ITEM_COLLECTION = '@shop-list:items' ;
export { LIST_COLLECTION , ITEM_COLLECTION } ;Exemple: joueur
Archives:
| -List | 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() pour gérer les éléments Nous pouvons utiliser le crochet useRef () pour accéder à la référence d'un élément , et ainsi traiter avec focus() , blur() , entre autres.
Exemple: En soumettant un formulaire, nous pouvons utiliser blur() dans l'élément d'entrée, après tout, l'utilisateur a déjà saisi ce qui était nécessaire, de sorte que l'effet desfoque peut mettre fin au clavier ouvert et supprimer la mise au point de l'entrée.
//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 >
) ; Afin que nous puissions distinguer une erreur générique / inconnue fournie par un throw et une erreur reconnue par notre application, nous pouvons créer une classe avec un attribut message et instancier cette classe, afin que nous puissions collecter instaceof <classe> dans le bloc catch .
Exemple:
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 ) ;
}
}Par: Rafael Ramos?