Einkaufslistendesign mit React Native und Expo .
git clone https://github.com/RafaelR4mos/challenge-react-native-shop-list.git package.json npm installnpm run startVerwenden Sie die Icon Library für die RN -Version.
npm install phosphor-react-nativeVerwendung von Symbolen:
import { Basket } from 'phosphor-react-native'
export function Componente() {
return (
<Basket
size={32}
color="#FFFFFF"
weight='bold'
/>
)
}
Stilisierte Komponenten und Verwendung von Themen. Der größte Unterschied für die Webversion ist das Tippen und notiert für die RN -Version
//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 -Attributen Damit es möglich ist, das Thema der Anwendung zu konsumieren und nicht in der .tsx -Datei selbst zu stylen styles.ts können wir den folgenden Code verwenden.
//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 auf TypeScript einWenn wir eine personalisierte Komponente erstellen und auch die Eingabe der nativen Komponente erweitern muss, können wir den Code als Basis verwenden:
//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 ;
} ; Wenn viele Variablen wie theme , type , variant und andere in einer Komponente verwendet werden, kann es nur sein, dass der css -Helfer der gestylerischen Komponenten zur Vereinfachung der Syntax beiträgt.
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 -Projekte npx expo install react-native-screens react-native-safe-area-contextnpm install @react-navigation/native-stackcontexto von Routen und 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 ist interessant zu erkennen, welche Routen in unserer Anwendung vorhanden sind und insbesondere welche params auf jedem der Routen erwartet werden
Erstellen Sie eine navigation.d.ts Datei
Schreiben Sie das Modul -Tipp in der Datei neu
export declare global {
namespace ReactNavigation {
interface RootParamList {
myLists : undefined ;
newList : undefined ;
list : {
listName : string ;
} ;
}
}
} Manchmal müssen wir Informationen zwischen den Seiten unserer Anwendung austauschen. Dafür können wir die Lib react-navigation und seine Haken verwenden
useNavigation() import { useNavigation } from '@react-navigation/native' ; const navigation = useNavigation ( ) ;navigate navigation . navigate ( 'route' , { state } ) ; Es ist wichtig, den Hook useRoute zu verwenden, der ebenfalls aus react-navigation stammt. Darin ist es möglich, die Parameter von route.params Parameter ideal ist auch tiar Was sind diese Parameter mit dem "as" + -Pot können
const route = useRoute ( ) ;
const { param } = route . params as RouteParams ; useFocusEffect für den Fokus auf die Seite useFocusEffect ist der useEffect ziemlich ähnlich. Sie wird jedoch aktiviert, wenn die Seite den Fokus erhält.
Import:
import { useFocusEffect } from '@react-navigation/native' ;Verwenden:
useFocusEffect (
useCallback ( ( ) => {
fetchLists ( ) ;
} , [ ] )
) ;
useCallBackwird zusammen verwendet, um ein unnötiges Rendering zu vermeiden, was bei der Anwendungsleistung helfen kann.
Ähnlich dem Browserort. Es kann dazu beitragen prop-drilling zu lösen, die die Informationen an einem Ort zentralisiert.
Installation:
npx expo instal @react-native-async-storage/async-storage
Die Dynamik des Umgangs mit AsyncStorage , ähnlich wie Lokalstor, aber asynchron ist unterschiedlich und es gibt ein Muster, das verwendet werden kann.
Erstellung eines Ordners nur für diesen storage
Erstellung einer Datei storageConfig.ts zum Definieren von Speichertasten
Damit garantieren wir eine bessere Wartung in den Schlüssel der in AsyncStorage gespeicherten Elemente
const LIST_COLLECTION = '@shop-list:lists' ;
const ITEM_COLLECTION = '@shop-list:items' ;
export { LIST_COLLECTION , ITEM_COLLECTION } ;Beispiel: Spieler
Archiv:
| -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() , um mit Elementen umzugehen Wir können den Hook UseSef () verwenden, um auf die Referenz eines Elements zuzugreifen und somit unter anderem mit focus() , blur() umzugehen.
Beispiel: Durch das Senden eines Formulars können wir blur() im Eingabeelement verwenden, schließlich hat der Benutzer bereits eingetragen, was benötigt wurde, sodass der desfoque die offene Tastatur beenden und den Fokus auf die Eingabe entfernen kann.
//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 >
) ; Damit wir einen generischen/unbekannten Fehler unterscheiden können, der durch einen throw und einen von unserer Anwendung erkannten Fehler geliefert wird, können wir eine Klasse mit einem message erstellen und diese Klasse instanziieren, damit wir instaceof <classe> innerhalb des catch sammeln können.
Beispiel:
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 ) ;
}
}Von: Rafael Ramos?