В Части I мы настраиваем модель данных продукта для нашего приложения электронной коммерции на основе Wordpress и Woo-commerce в качестве источника данных, вы можете ознакомиться с документацией. и построен с использованием Ignite Bowser. Во второй части мы собираемся подключить несколько экранов, чтобы завершить жизненный цикл данных!
Перво-наперво нам нужен экран. Создадим один:
ignite g screen shop
Теперь у нас есть пустой экран с именем shop-screen.tsx
. Давайте заменим экран приветствия и демонстрацию, которые поставляются с Bowser, на этот новый экран. Теперь наш основной навигатор должен выглядеть так:
Прежде чем запустить приложение, давайте исправим несколько вещей:
Добавьте запись в en.json
для перевода текста этого экрана:
"shopScreen": { "header": "Shop" }
Обновите шкалу интервалов в app/theme/spacing.ts
, чтобы:
export const spacing = { tiny: 4, small: 8, medium: 12, large: 24, extraLarge: 48, huge: 64, }
- Добавьте
flex: 1
к нашему основному компоненту и немного отступов вокруг заголовка.
Вот что у нас получается:
Когда мы запускаем приложение, оно выглядит так:
Добавление данных
Наш экран выглядит немного пустым, так что давайте добавим данные!
Сначала мы внедрим наш магазин MST:
раскомментировать:
import { useStores } from "../models/root-store"
затем убедитесь, что ваш экран делает это:
export const ShopScreen: React.FunctionComponent<ShopScreenProps> = observer((props) => { const { rootStore } = useStores() return ( <Screen style={ROOT} preset="scroll"> <View style={HEADER_CONTAINER}> <Text preset="header" tx="shopScreen.header" /> </View> </Screen> ) })
Мы успешно импортировали наше корневое хранилище, теперь мы можем создавать получение данных из хранилища.
Стилизация выходит за рамки этого руководства, поэтому я просто предоставлю пакеты, которые я использую, а также снимок экрана с кодом, поэтому я использую:
react-native-design-utility
это очень полезно для стилизации, я сначала создал презентационный компонент под названием productCard, который я буду использовать в плоском списке, вот как вы создаете компонент:
ignite generate component productCard
Затем просто вставьте это:
import * as React from "react" import { View, ViewStyle, ImageStyle, Image, TouchableOpacity, Animated, TouchableWithoutFeedback, TextStyle } from "react-native" import { Box, Text } from "react-native-design-utility" import { productCardStyles as styles } from "./productCard.styles" export interface ProductCardProps { /** * Text which is looked up via i18n. */ tx?: string /** * The text to display if not using `tx` or nested components. */ text?: string /** * The product array */ product?: any /** * An optional style override useful for padding & margin. */ style?: ViewStyle } /** * Stateless functional component for your needs * * Component description here for TypeScript tips. */ const PRODUCT_IMAGE: ImageStyle = { width: 120, height: 100, } const PRODUCT_TITLE: TextStyle = { fontSize: 14, color: '#000000', textAlign: 'left', marginTop: 5, textTransform: "lowercase", } const PRODUCT_PRICE: TextStyle = { fontWeight: '600', fontSize: 16, paddingLeft: 20, color: '#000000', paddingBottom: 5, paddingTop: 5, textAlign: 'right', } const PRODUCT_CONTAINER = { marginLeft: 30, marginBottom: 30, } export function ProductCard(props: ProductCardProps) { // grab the props const { tx, text, style, product, ...rest } = props const textStyle = { } return ( <Box bg="white" w={160} p="sm" position="relative" shadow={0} style={PRODUCT_CONTAINER}> <Box> <Box mb="sm"> <Image style={PRODUCT_IMAGE} resizeMode="contain" source={{ uri: product.featured_src }} /> </Box> <Box> <Text left size="sm" bold style={PRODUCT_PRICE}> R{product.price} </Text> <Text left size="xs" style={PRODUCT_TITLE}> {product.title} </Text> </Box> </Box> </Box> ) }
Затем на экране магазина:
import React, { useEffect, useState } from "react" import { observer } from "mobx-react-lite" import { Image, ViewStyle, TextStyle, ScrollView, FlatList, TouchableOpacity, View, SafeAreaView } from "react-native" import { Screen, Text, ProductCard, Button } from "../components" import { useStores } from "../models/root-store" import { spacing, color } from "../theme" import { NavigationScreenProps } from "react-navigation" import { Box } from "react-native-design-utility" export interface ShopScreenProps extends NavigationScreenProps<{}> { } const ROOT: ViewStyle = { flex: 1, paddingHorizontal: spacing.large, backgroundColor: color.palette.black, } const HEADER_CONTAINER: ViewStyle = { marginTop: spacing.extraLarge, marginBottom: spacing.medium, } const GRID_VIEW = { marginTop: 20, flex: 1, } export const ShopScreen: React.FunctionComponent<ShopScreenProps> = observer((props) => { const rootStore = useStores() const fetchProducts = () => { rootStore.productStore.getProducts() } const [refreshing, setRefreshing] = useState(false) useEffect(() => { setRefreshing(true) fetchProducts() setRefreshing(false) }) const renderItem = ({ item }) => <ProductCard product={item} /> const keyExtractor = item => String(item.id) const renderList = () => { if (rootStore.productStore.products.length === 0) { return ( <Box center f={1}> <Text>Products Empty</Text> </Box> ) } return ( <FlatList data={rootStore.productStore.products} style={GRID_VIEW} renderItem={renderItem} numColumns={2} keyExtractor={keyExtractor} onRefresh={fetchProducts} refreshing={refreshing} /> ) } return ( <Screen style={ROOT} preset="scroll"> <View style={HEADER_CONTAINER}> <Text preset="header" tx="shopScreen.header" /> </View> {renderList()} </Screen> ) })
После этого получаем вот что:
Это вторая часть! Теперь у нас есть данные, отображаемые в нашем пользовательском интерфейсе, мы создали презентационный компонент, подключили его к реквизитам и использовали в плоском списке. В следующий раз, в части III, мы создадим функциональность корзины покупок и немного изменим стиль пользовательского интерфейса.