Дизайн списка покупок с 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 на 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 и другие в одном компоненте, может быть только то, что Helper 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 ;
} ;
}
}
} Время от времени нам нужно обмениваться информацией между страницами нашего приложения, мы можем использовать либеат 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 также является тиаром, что это за параметры с «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 | listgetGall.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 ) ;
}
}Автор: Рафаэль Рамос?