تصميم قائمة الشراء مع React Native and Expo .
git clone https://github.com/RafaelR4mos/challenge-react-native-shop-list.git package.json npm installnpm run startاستخدم مكتبة الأيقونة لإصدار RN.
npm install phosphor-react-nativeاستخدام الرموز:
import { Basket } from 'phosphor-react-native'
export function Componente() {
return (
<Basket
size={32}
color="#FFFFFF"
weight='bold'
/>
)
}
مكونات منمقة واستخدام الموضوعات. الفرق الأكبر لإصدار الويب هو في الكتابة والإشارة إلى إصدار 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 بحيث يكون من الممكن استهلاك موضوع التطبيق وليس الاضطرار إلى التصميم في ملف .tsx نفسه يمكننا استخدامه في styles.ts .
//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 على TypeScriptإذا أنشأنا مكونًا مخصصًا وكان من الضروري أيضًا تمديد كتابة المكون الأصلي ، فيمكننا استخدام الكود كقاعدة:
//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 ;
} ; عندما يكون هناك استخدام للعديد من المتغيرات مثل theme type variant وغيرها في مكون واحد ، قد يكون فقط أن المساعد css المصنوع من التصميم يساهم في تبسيط بناء الجملة.
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 الطرق 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/ من المثير للاهتمام معرفة الطرق الموجودة في تطبيقنا وخاصة params هو متوقع في كل من الطرق
قم بإنشاء ملف navigation.d.ts
أعد كتابة كتابة الوحدة في الملف
export declare global {
namespace ReactNavigation {
interface RootParamList {
myLists : undefined ;
newList : undefined ;
list : {
listName : string ;
} ;
}
}
} في بعض الأحيان ، نحتاج إلى تبادل المعلومات بين صفحات تطبيقنا ، لهذا ، يمكننا استخدام Lib react-navigation و Hands له
useNavigation() import { useNavigation } from '@react-navigation/native' ; const navigation = useNavigation ( ) ;navigate navigation . navigate ( 'route' , { state } ) ; من المهم استخدام Hook useRoute ، الذي يأتي أيضًا من react-navigation . في هذا ، من الممكن تعطيل المعلمات من route.params Params Ideial هو أيضا tiar ما هي هذه المعايير مع "AS" + Tipage
const route = useRoute ( ) ;
const { param } = route . params as RouteParams ; useFocusEffect للتركيز على الصفحة يشبه useFocusEffect تمامًا useEffect ، ومع ذلك يتم تنشيطه كلما تلقيت الصفحة التركيز ، أي بالإضافة إلى الحمل الأول ، يتم استدعاءه في حالة حدوث تنقل للصفحة
يستورد:
import { useFocusEffect } from '@react-navigation/native' ;يستخدم:
useFocusEffect (
useCallback ( ( ) => {
fetchLists ( ) ;
} , [ ] )
) ;يتم استخدام
useCallBackمعًا لتجنب إطلاق العرض غير الضروري ، والذي يمكن أن يساعد في أداء التطبيق.
على غرار موقع المتصفح. يمكن أن يساعد في حل مشاكل prop-drilling لأنه يركز على المعلومات في مكان واحد.
تثبيت:
npx expo instal @react-native-async-storage/async-storage
ديناميات التعامل مع AsyncStorage ، على غرار LocalStorage ، ولكن غير متزامن مختلف وهناك نمط يمكن استخدامه.
إنشاء مجلد فقط لهذا storage
إنشاء ملف storageConfig.ts لتحديد مفاتيح التخزين
مع هذا ، نضمن صيانة أفضل في مفاتيح العناصر المحفوظة في AsyncStorage
const LIST_COLLECTION = '@shop-list:lists' ;
const ITEM_COLLECTION = '@shop-list:items' ;
export { LIST_COLLECTION , ITEM_COLLECTION } ;مثال: لاعب
أرشيف:
| قائمة | 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() للتعامل مع العناصر يمكننا استخدام الخطاف useref () للوصول إلى مرجع عنصر ، وبالتالي التعامل مع focus() ، blur() ، من بين أمور أخرى.
مثال: من خلال إرسال نموذج ، يمكننا استخدام blur() في عنصر الإدخال ، بعد كل شيء ، أدخل المستخدم بالفعل ما هو مطلوب ، بحيث يمكن أن ينهي تأثير desfoque لوحة المفاتيح المفتوحة وإزالة التركيز على الإدخال.
//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 >
) ; حتى نتمكن من التمييز بين خطأ عام/غير معروف يوفره throw وخطأ معترف به من خلال تطبيقنا ، يمكننا إنشاء فئة مع سمة message وتثبيت هذه الفئة ، حتى نتمكن من جمع instaceof <classe> داخل كتلة catch .
مثال:
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 ) ;
}
}بقلم: رافائيل راموس؟