reactjs - 在 react-native 的两个页面之间传输数据之前需要它
问题描述
我想在我的应用程序的两个页面之间传输数据,通常我的语法没有任何问题,this.props.navigation.state.params...
但在这种情况下,问题是 itemCategory 是未定义的,因为我的第一页(初始路由)是HomeScreen
,而我的第二页是CategoryListScreen
. 那么究竟发生了什么:
- 用户启动应用程序并登陆主屏幕
在构造函数中,我正在尝试使用暂时未定义的 itemCategory 修改状态类别
this.state = { 类别:this.props.navigation.state.params.itemCategory, restaurantData: [], }
应用程序崩溃,因为 this.props.navigation.state.params.itemCategory 未定义
我试图更改初始路由,CategoryListScreen
并且数据已正确设置在我的 HomeScreen 页面的状态类别中,因为它现在是我的第二页。
所以我想知道的是如何设置变量类别而不会使应用程序崩溃......
用户使用CategoryListScreen
来选择他想吃的食物类型,因此我可以调用我的 API 以仅显示具有此类食物的餐厅。
/*Beginning CategoryListScreen*/
import PropTypes from 'prop-types'
import React, { Component } from 'react'
import { FlatList, Image, Text, TouchableOpacity, View } from 'react-native'
import {environment} from '../../environments/environment'
import axios from '../../interceptor/tokenInterceptor'
import Hamburger from '../../components/Hamburger/Hamburger'
import styles from './styles'
const menuData = [
{
id: '1',
title: 'Burger',
image: require('../../assets/images/burger.jpg'),
},
{
id: '2',
title: 'Pizza',
image: require('../../assets/images/pizza.jpeg'),
},
{
id: '3',
title: 'Sushi',
image: require('../../assets/images/sushi.jpg'),
},
{
id: '4',
title: 'Tacos',
image: require('../../assets/images/tacos.jpeg'),
},
{
id: '5',
title: 'Chinois',
image: require('../../assets/images/plat_chinois.jpg'),
},
{
id: '6',
title: 'Français',
image: require('../../assets/images/plat_français.jpg'),
},
{
id: '7',
title: 'Mexicain',
image: require('../../assets/images/mexicain.jpg'),
},
{
id: '8',
title: 'Italien',
image: require('../../assets/images/italien.jpg'),
},
]
class CategoryListScreen extends Component {
static navigationOptions = ({navigation}) => ({
title: 'Menu',
headerLeft: (
<Hamburger
onPress={() => {
navigation.openDrawer()
}}
/>
),
})
constructor(props) {
super(props)
this.state = {
restaurantData: [],
}
}
onPress = itemCategory => {
// console.log('category : ', itemCategory);
this.props.navigation.navigate('HomeScreen', {itemCategory})
// console.log(item);
// this.getRestaurantByCategories(item)
}
renderItem = ({item}) => (
<TouchableOpacity onPress={() => this.onPress(item.title)}>
<View style={styles.container}>
<Image style={styles.photo} source={item.image}/>
<View style={styles.overlay} />
<Text numberOfLines={3} style={styles.title}>
{item.title}
</Text>
</View>
</TouchableOpacity>
)
render() {
return (
<FlatList
vertical
showsVerticalScrollIndicator={false}
numColumns={2}
data={menuData}
renderItem={this.renderItem}
keyExtractor={item => `${item.id}`}
/>
)
}
}
CategoryListScreen.propTypes = {
navigation: PropTypes.shape({
navigate: PropTypes.func.isRequired,
}),
}
export default CategoryListScreen
/*End CategoryListScreen*/
/*Beginning HomeScreen*/
import PropTypes from 'prop-types'
import React from 'react'
import {
AsyncStorage,
FlatList,
Image,
ScrollView,
Text,
TouchableHighlight,
View,
} from 'react-native'
import _ from 'lodash'
import Hamburger from '../../components/Hamburger/Hamburger'
import ShoppingCartButton from '../../components/ShoppingCartButton/ShoppingCartButton'
import {environment} from '../../environments/environment'
import axios from '../../interceptor/tokenInterceptor'
import styles from './styles'
const categoriesData = [
{
id: '1',
title: 'Burger',
image: require('../../assets/images/burger.jpg'),
},
{
id: '2',
title: 'Pizza',
image: require('../../assets/images/pizza.jpeg'),
},
{
id: '3',
title: 'Sushi',
image: require('../../assets/images/sushi.jpg'),
},
{
id: '4',
title: 'Tacos',
image: require('../../assets/images/tacos.jpeg'),
},
{
id: '5',
title: 'Chinois',
image: require('../../assets/images/plat_chinois.jpg'),
},
{
id: '6',
title: 'Cuisine',
image: require('../../assets/images/plat_français.jpg'),
},
]
/**
* Construit le component catégorie en haut de la page
*/
ItemCategory = ({title, image}) => {
return (
<View>
<Image source={image} style={styles.categoryItemPhoto} />
<Text style={styles.categoryItemTitle}>{title}</Text>
</View>
)
}
/**
* Construit les composant restaurant
*/
ItemRestaurant = ({id, title, image, distance, categories}) => {
return (
<View>
{/* <Text>{id}</Text> */}
{/* <Image source={{uri: `data:image/png;base64,${image}`}} style={styles.foodPhoto}/> */}
<Text style={styles.title}>{title}</Text>
<Text style={styles.textRestaurant}>
distance depuis votre position : {distance}m
</Text>
<Text style={styles.textRestaurant}>Catégories : {`${categories}`}</Text>
</View>
)
}
export default class HomeScreen extends React.Component {
static navigationOptions = ({navigation}) => ({
title: 'Home',
headerLeft: () => (
<Hamburger
onPress={() => {
navigation.openDrawer()
}}
/>
),
headerRight: () => (
<ShoppingCartButton
onPress={() => {
navigation.navigate('CartScreen')
}}
/>
),
})
constructor(props) {
super(props)
// if (this.props.navigation.state.params.itemCategory === undefined) {
// console.log('dans le if')
// this.state = {
// restaurantData: [],
// }
// } else {
// this.state = {
// categories: this.props.navigation.state.params.itemCategory,
// restaurantData: [],
// }
// }
// if (this.props.navigation.state.params.itemCategory === undefined) {
// console.log('je suis undefined');
// }
this.state = {
// categories: this.props.navigation.state.params.itemCategory,
categories: this.props.navigation.getParam('itemCategory', 'NO_VALUE'),
// categories: _.get(this.props, 'navigation.state.params.itemCategory'),
restaurantData: [],
}
}
componentDidMount() {
console.log('dans le componentdidmount : ', this.state.categories);
this.getRestaurant()
}
/**
* Récupère la liste de tous les restaurants à moins de 30km du user
*/
getRestaurant = async () => {
try {
let res = await axios({
method: 'get',
url: `${environment.apiDevUrl}/restaurant/visible`,
})
this.setState({
restaurantData: res.data,
})
} catch (error) {
console.error(error)
}
}
getCategories = async () => {
try {
let res = await axios({
method: 'get',
url: `${environment.apiDevUrl}/restaurant/category/Pizza`,
})
} catch (error) {
console.error(error)
}
}
/**
* Affiche seulement les restaurants en fonction de la catégorie choisi par le user
*/
getRestaurantByCategories = async (item) => {
console.log('item : ',item);
try {
let res = await axios({
method: 'post',
url: `${environment.apiDevUrl}/restaurant/category`,
headers: {'Content-Type': 'application/json'},
data: {
category: item
}
})
this.setState({restaurantData: res.data})
console.log('restaurantData : ', this.state.restaurantData);
return res.data
} catch (error) {
console.error(error);
}
}
onPressCategoryItem = item => {
this.getRestaurantByCategories(item.title)
}
onPressRestaurantItem = item => {
this.props.navigation.navigate('RestaurantDetailScreen', {item})
}
initCartFromPersistentStore() {
AsyncStorage.getItem('@MySuperCart:key')
.then(res => {
if (res != null) {
const array = JSON.parse(res)
console.log(array)
this.props.navigation.dispatch({type: 'Override', items: array})
}
})
.catch(error => {
console.log(`Promise is rejected with error: ${error}`)
})
}
renderCategoryItem = ({item}) => (
<TouchableHighlight onPress={() => this.onPressCategoryItem(item)}>
<View style={styles.categoryItemContainer}>
<ItemCategory image={item.image} title={item.title} />
</View>
</TouchableHighlight>
)
renderRestaurantItem = ({item}) => (
<TouchableHighlight onPress={() => this.onPressRestaurantItem(item.restaurant.id)}>
<View style={styles.foodItemContainer}>
<ItemRestaurant
// id={item.restaurant.id}
image={item.restaurant.image}
title={item.restaurant.nom}
distance={item.distance}
categories={item.restaurant.categorie}
/>
</View>
</TouchableHighlight>
)
render() {
console.log('dans le render : ', this.state.categories);
// const categoryFromList = this.props.navigation.state.params.itemCategory
// console.log('category dans homescreen : ',categoryFromList);
return (
<ScrollView style={styles.container}>
<Text style={styles.title}> Catégories populaires</Text>
<View style={styles.categories}>
<FlatList
horizontal
initialNumToRender={4}
data={categoriesData}
showsHorizontalScrollIndicator={false}
renderItem={this.renderCategoryItem}
keyExtractor={item => `${item.id}`}
/>
</View>
<Text style={styles.title}> Restaurants </Text>
<View style={styles.foods}>
<FlatList
initialNumToRender={2}
data={this.state.restaurantData}
renderItem={this.renderRestaurantItem}
keyExtractor={item => `${item.restaurant.id}`}
/>
</View>
</ScrollView>
)
}
}
HomeScreen.propTypes = {
navigation: PropTypes.shape({
navigate: PropTypes.func.isRequired,
}),
}
/*End HomeScreen*/
解决方案
最简单的方法是添加Lodash模块并执行以下操作:
import _ from 'lodash'
....
this.state = {
categories: _.get(this.props, 'navigation.state.params.itemCategory'),
restaurantData: []
}
...
这样你的应用程序就不会崩溃。
推荐阅读
- linux - 哪个进程发送 SIGKILL 并终止我的 Namecheap 服务器上的所有 SSH 连接?
- javascript - 在Javascript中的if块中动态放置条件
- java - 使用 android studio java Recycler 视图从 Firebase 实时数据库中删除节点
- c# - MediatR 定制行为管道
- java - 多变量函数的数值微分
- c++ - 构造实例的最佳实践
- javascript - 将 prop 从中间组件传递到 props.children
- c++ - 如何使用 gdb 在 vscode 中查看结构的非漂亮版本?
- javascript - 如何访问此 javascript 对象以进行动态 src 更新(plyr html5
- typescript - Typescript - 文字类型推断 - 与字符串和数字不同的行为