Desain daftar pembelian dengan React Native dan Expo .
git clone https://github.com/RafaelR4mos/challenge-react-native-shop-list.git package.json npm installnpm run startGunakan perpustakaan Icon untuk versi RN.
npm install phosphor-react-nativePenggunaan ikon:
import { Basket } from 'phosphor-react-native'
export function Componente() {
return (
<Basket
size={32}
color="#FFFFFF"
weight='bold'
/>
)
}
Komponen bergaya dan penggunaan tema. Perbedaan terbesar untuk versi web adalah dalam mengetik dan mencatat untuk versi 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 Sehingga dimungkinkan untuk mengkonsumsi tema aplikasi dan tidak harus menata file .tsx itu sendiri yang dapat kita gunakan dalam styles.ts kode berikut:
//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 pada naskahJika kita membuat komponen yang dipersonalisasi dan juga perlu untuk memperluas pengetikan komponen asli, kita dapat menggunakan kode sebagai basis:
//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 ;
} ; Ketika ada penggunaan banyak variabel seperti theme , type , variant , dan lainnya dalam satu komponen, mungkin hanya penolong css yang berkontribusi untuk menyederhanakan sintaks.
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 rute dan 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/ Sangat menarik untuk mengetahui rute mana yang ada dalam aplikasi kami dan terutama params mana yang diharapkan pada masing -masing rute
Buat file navigation.d.ts
Tulis ulang pengetikan modul di file
export declare global {
namespace ReactNavigation {
interface RootParamList {
myLists : undefined ;
newList : undefined ;
list : {
listName : string ;
} ;
}
}
} Kadang-kadang kita perlu bertukar informasi antar halaman aplikasi kita, untuk ini, kita dapat menggunakan react-navigation lib dan kaitnya
useNavigation() import { useNavigation } from '@react-navigation/native' ; const navigation = useNavigation ( ) ;navigate navigation . navigate ( 'route' , { state } ) ; Penting untuk menggunakan hook useRoute , yang juga berasal dari react-navigation . Dalam hal ini dimungkinkan untuk mengganggu parameter dari dalam route.params Params Idideial juga tiar apa param ini dengan "AS" + Tipage
const route = useRoute ( ) ;
const { param } = route . params as RouteParams ; useFocusEffect untuk fokus pada halaman useFocusEffect sangat mirip dengan useEffect , namun diaktifkan setiap kali halaman menerima fokus, yaitu selain beban pertama yang dipanggil jika navigasi terjadi pada halaman tersebut
Impor:
import { useFocusEffect } from '@react-navigation/native' ;Menggunakan:
useFocusEffect (
useCallback ( ( ) => {
fetchLists ( ) ;
} , [ ] )
) ;
useCallBackdigunakan bersama untuk menghindari menembakkan rendering yang tidak perlu, yang dapat membantu dengan kinerja aplikasi.
Mirip dengan lokasi browser. Ini dapat membantu memecahkan masalah prop-drilling karena memusatkan informasi di satu tempat.
Instalasi:
npx expo instal @react-native-async-storage/async-storage
Dinamika berurusan dengan AsyncStorage , mirip dengan LocalStorage, tetapi asinkron berbeda dan ada pola yang dapat digunakan.
Pembuatan folder hanya untuk storage ini
Pembuatan file storageConfig.ts untuk menentukan kunci penyimpanan
Dengan ini, kami menjamin pemeliharaan yang lebih baik dalam kunci elemen yang disimpan di AsyncStorage
const LIST_COLLECTION = '@shop-list:lists' ;
const ITEM_COLLECTION = '@shop-list:items' ;
export { LIST_COLLECTION , ITEM_COLLECTION } ;Contoh: pemain
Arsip:
| -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() untuk menangani elemen Kita dapat menggunakan hook useref () untuk mengakses referensi elemen , dan dengan demikian berurusan dengan focus() , blur() , antara lain.
Contoh: Dengan mengirimkan formulir, kita dapat menggunakan blur() di elemen input, setelah semua, pengguna telah memasukkan apa yang diperlukan, sehingga efek desfoque dapat mengakhiri keyboard terbuka dan menghapus fokus ke input.
//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 >
) ; Sehingga kita dapat membedakan kesalahan generik/tidak diketahui yang disediakan oleh throw dan kesalahan yang dikenali oleh aplikasi kita, kita dapat membuat kelas dengan atribut message dan instantiate kelas ini, sehingga kita dapat mengumpulkan instaceof <classe> di dalam blok catch .
Contoh:
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 ) ;
}
}Oleh: Rafael Ramos?