การออกแบบรายการจัดซื้อด้วย React Native และ 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 on 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 และตะขอของเขา
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 แต่จะเปิดใช้งานเมื่อใดก็ตามที่หน้ารับโฟกัสเช่น การโหลดครั้งที่ 1 จะถูกเรียกใช้หากมีการนำทางไปยังหน้าเว็บ
นำเข้า:
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() เพื่อจัดการกับองค์ประกอบ เราสามารถใช้ hook 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 Block
ตัวอย่าง:
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 ) ;
}
}โดย: Rafael Ramos?