В Части 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, мы создадим функциональность корзины покупок и немного изменим стиль пользовательского интерфейса.