React Native 在两个 class 组件中传递和获取参数
React Native pass and get params in two class components
我遇到了这个错误,但我找不到原因。我几个小时以来一直在寻找答案,但我就是找不到。如果有人可以提供帮助,将非常高兴。
我点击卡片试图导航到详细信息页面,只是简单地不传递参数:
当我尝试在此 class 中调用它时,我总是收到此错误:
提前感谢您的帮助!
这就是在 class 组件中获取参数的方法:
render(props) {
const {item} = this.props.route.params;
return()
}
这是第一个class:
import React, {Component} from 'react';
import { View, Text, ScrollView, ActivityIndicator, Button, FlatList, StyleSheet } from 'react-native';
import Card from '../../common/Card/Card';
import { ListItem } from 'react-native-elements'
import firestore from '@react-native-firebase/firestore';
import storage from "@react-native-firebase/storage";
class CardListScreen extends Component {
constructor() {
super();
this.firestoreRef = firestore().collection('restaurants');
this.state = {
isLoading: true,
userArr: []
};
}
componentDidMount() {
this.unsubscribe = this.firestoreRef.onSnapshot(this.getCollection);
}
componentWillUnmount(){
this.unsubscribe();
}
getCollection = (querySnapshot) => {
const userArr = [];
querySnapshot.forEach((res) => {
const { title, description, rating, reviews, bannerUrl } = res.data();
const store = [];
const card = {
key: res.id,
res,
title,
description,
rating,
bannerUrl,
categories: [],
reviews,
};
userArr.push(card);
firestore()
.collection('restaurants')
.doc(res.id)
.onSnapshot(documentSnapshot => {
store.push(documentSnapshot.data());
store.map((num) => {
card["categories"] = num.categories;
userArr.push(card);
})
});
});
this.setState({
userArr,
isLoading: false,
});
}
render() {
if(this.state.isLoading){
return(
<View style={styles.preloader}>
<ActivityIndicator size="large" color="#9E9E9E"/>
</View>
)
}
return (
<ScrollView style={styles.container}>
{
this.state.userArr.map((item, i) => {
return (
<Card
key={i}
itemData={item}
onPress={()=> this.props.navigation.navigate('CardItemDetails', {itemData: item})}
/>
);
})
}
</ScrollView>
);
}
};
export default CardListScreen;
const styles = StyleSheet.create({
container: {
flex: 1,
paddingBottom: 22,
marginHorizontal: 10,
},
preloader: {
left: 0,
right: 0,
top: 0,
bottom: 0,
position: 'absolute',
alignItems: 'center',
justifyContent: 'center'
}
});
这是第二个class:
import React, {useRef, Component} from 'react';
import {
View,
Text,
Image,
StyleSheet,
Dimensions,
StatusBar,
Platform,
} from 'react-native';
import { ImageHeaderScrollView, TriggeringView } from 'react-native-image-header-scroll-view';
import * as Animatable from 'react-native-animatable';
import MapView, {PROVIDER_GOOGLE} from 'react-native-maps';
import FontAwesome from 'react-native-vector-icons/FontAwesome';
const MIN_HEIGHT = Platform.OS === 'ios' ? 90 : 55;
const MAX_HEIGHT = 350;
class CardItemDetails extends Component {
render(props) {
const itemData = props.itemData;
const navTitleView = useRef(null);
return (
<View style={styles.container}>
<StatusBar barStyle="light-content" />
<ImageHeaderScrollView
maxHeight={MAX_HEIGHT}
minHeight={MIN_HEIGHT}
maxOverlayOpacity={0.6}
minOverlayOpacity={0.3}
renderHeader={() => (
<Image source={{uri: itemData.bannerUrl}} style={styles.image} />
)}
renderForeground={() => (
<View style={styles.titleContainer}>
<Text style={styles.imageTitle}>{itemData.title}</Text>
</View>
)}
renderFixedForeground={() => (
<Animatable.View style={styles.navTitleView} ref={navTitleView}>
<Text style={styles.navTitle}>{itemData.title}</Text>
</Animatable.View>
)}>
<TriggeringView
style={styles.section}
onHide={() => navTitleView.current.fadeInUp(200)}
onDisplay={() => navTitleView.current.fadeOut(100)}>
<View style={{flexDirection: 'row', justifyContent: 'space-between'}}>
<Text style={styles.title}>Overview</Text>
<View style={{flexDirection: 'row', alignItems: 'flex-end'}}>
<FontAwesome name="star" size={16} color="#FF6347" />
<Text style={{marginHorizontal: 2}}>{itemData.rating}</Text>
<Text>({itemData.reviews})</Text>
</View>
</View>
</TriggeringView>
<View style={[styles.section, styles.sectionLarge]}>
<Text style={styles.sectionContent}>{itemData.description}</Text>
</View>
<View style={styles.section}>
<View style={styles.categories}>
{itemData.categories.map((category, index) => (
<View style={styles.categoryContainer} key={index}>
<FontAwesome name="tag" size={16} color="#fff" />
<Text style={styles.category}>{category}</Text>
</View>
))}
</View>
</View>
<View style={[styles.section, {height: 250}]}>
{/*<MapView
provider={PROVIDER_GOOGLE}
style={{flex: 1}}
region={{
latitude: Number(itemData.coordinate[0]),
longitude: Number(itemData.coordinate[1]),
latitudeDelta: 0.00864195044303443,
longitudeDelta: 0.000142817690068,
}}>
<MapView.Marker
coordinate={itemData.coordinate}
image={require('../../assets/images/map_marker.png')}
/>
</MapView>*/}
</View>
</ImageHeaderScrollView>
</View>
);
}
};
export default CardItemDetails;
const styles = StyleSheet.create({
container: {
flex: 1,
},
image: {
height: MAX_HEIGHT,
width: Dimensions.get('window').width,
alignSelf: 'stretch',
resizeMode: 'cover',
},
title: {
fontSize: 20,
},
name: {
fontWeight: 'bold',
},
section: {
padding: 20,
borderBottomWidth: 1,
borderBottomColor: '#cccccc',
backgroundColor: 'white',
},
sectionTitle: {
fontSize: 18,
fontWeight: 'bold',
},
sectionContent: {
fontSize: 16,
textAlign: 'justify',
},
categories: {
flexDirection: 'row',
justifyContent: 'flex-start',
alignItems: 'flex-start',
flexWrap: 'wrap',
},
categoryContainer: {
flexDirection: 'row',
backgroundColor: '#FF6347',
borderRadius: 20,
margin: 10,
padding: 10,
paddingHorizontal: 15,
},
category: {
fontSize: 14,
color: '#fff',
marginLeft: 10,
},
titleContainer: {
flex: 1,
alignSelf: 'stretch',
justifyContent: 'center',
alignItems: 'center',
},
imageTitle: {
color: 'white',
backgroundColor: 'transparent',
fontSize: 24,
},
navTitleView: {
height: MIN_HEIGHT,
justifyContent: 'center',
alignItems: 'center',
paddingTop: Platform.OS === 'ios' ? 40 : 5,
opacity: 0,
},
navTitle: {
color: 'white',
fontSize: 18,
backgroundColor: 'transparent',
},
sectionLarge: {
minHeight: 300,
},
});
我遇到了这个错误,但我找不到原因。我几个小时以来一直在寻找答案,但我就是找不到。如果有人可以提供帮助,将非常高兴。
我点击卡片试图导航到详细信息页面,只是简单地不传递参数:
当我尝试在此 class 中调用它时,我总是收到此错误:
提前感谢您的帮助!
这就是在 class 组件中获取参数的方法:
render(props) {
const {item} = this.props.route.params;
return()
}
这是第一个class:
import React, {Component} from 'react';
import { View, Text, ScrollView, ActivityIndicator, Button, FlatList, StyleSheet } from 'react-native';
import Card from '../../common/Card/Card';
import { ListItem } from 'react-native-elements'
import firestore from '@react-native-firebase/firestore';
import storage from "@react-native-firebase/storage";
class CardListScreen extends Component {
constructor() {
super();
this.firestoreRef = firestore().collection('restaurants');
this.state = {
isLoading: true,
userArr: []
};
}
componentDidMount() {
this.unsubscribe = this.firestoreRef.onSnapshot(this.getCollection);
}
componentWillUnmount(){
this.unsubscribe();
}
getCollection = (querySnapshot) => {
const userArr = [];
querySnapshot.forEach((res) => {
const { title, description, rating, reviews, bannerUrl } = res.data();
const store = [];
const card = {
key: res.id,
res,
title,
description,
rating,
bannerUrl,
categories: [],
reviews,
};
userArr.push(card);
firestore()
.collection('restaurants')
.doc(res.id)
.onSnapshot(documentSnapshot => {
store.push(documentSnapshot.data());
store.map((num) => {
card["categories"] = num.categories;
userArr.push(card);
})
});
});
this.setState({
userArr,
isLoading: false,
});
}
render() {
if(this.state.isLoading){
return(
<View style={styles.preloader}>
<ActivityIndicator size="large" color="#9E9E9E"/>
</View>
)
}
return (
<ScrollView style={styles.container}>
{
this.state.userArr.map((item, i) => {
return (
<Card
key={i}
itemData={item}
onPress={()=> this.props.navigation.navigate('CardItemDetails', {itemData: item})}
/>
);
})
}
</ScrollView>
);
}
};
export default CardListScreen;
const styles = StyleSheet.create({
container: {
flex: 1,
paddingBottom: 22,
marginHorizontal: 10,
},
preloader: {
left: 0,
right: 0,
top: 0,
bottom: 0,
position: 'absolute',
alignItems: 'center',
justifyContent: 'center'
}
});
这是第二个class:
import React, {useRef, Component} from 'react';
import {
View,
Text,
Image,
StyleSheet,
Dimensions,
StatusBar,
Platform,
} from 'react-native';
import { ImageHeaderScrollView, TriggeringView } from 'react-native-image-header-scroll-view';
import * as Animatable from 'react-native-animatable';
import MapView, {PROVIDER_GOOGLE} from 'react-native-maps';
import FontAwesome from 'react-native-vector-icons/FontAwesome';
const MIN_HEIGHT = Platform.OS === 'ios' ? 90 : 55;
const MAX_HEIGHT = 350;
class CardItemDetails extends Component {
render(props) {
const itemData = props.itemData;
const navTitleView = useRef(null);
return (
<View style={styles.container}>
<StatusBar barStyle="light-content" />
<ImageHeaderScrollView
maxHeight={MAX_HEIGHT}
minHeight={MIN_HEIGHT}
maxOverlayOpacity={0.6}
minOverlayOpacity={0.3}
renderHeader={() => (
<Image source={{uri: itemData.bannerUrl}} style={styles.image} />
)}
renderForeground={() => (
<View style={styles.titleContainer}>
<Text style={styles.imageTitle}>{itemData.title}</Text>
</View>
)}
renderFixedForeground={() => (
<Animatable.View style={styles.navTitleView} ref={navTitleView}>
<Text style={styles.navTitle}>{itemData.title}</Text>
</Animatable.View>
)}>
<TriggeringView
style={styles.section}
onHide={() => navTitleView.current.fadeInUp(200)}
onDisplay={() => navTitleView.current.fadeOut(100)}>
<View style={{flexDirection: 'row', justifyContent: 'space-between'}}>
<Text style={styles.title}>Overview</Text>
<View style={{flexDirection: 'row', alignItems: 'flex-end'}}>
<FontAwesome name="star" size={16} color="#FF6347" />
<Text style={{marginHorizontal: 2}}>{itemData.rating}</Text>
<Text>({itemData.reviews})</Text>
</View>
</View>
</TriggeringView>
<View style={[styles.section, styles.sectionLarge]}>
<Text style={styles.sectionContent}>{itemData.description}</Text>
</View>
<View style={styles.section}>
<View style={styles.categories}>
{itemData.categories.map((category, index) => (
<View style={styles.categoryContainer} key={index}>
<FontAwesome name="tag" size={16} color="#fff" />
<Text style={styles.category}>{category}</Text>
</View>
))}
</View>
</View>
<View style={[styles.section, {height: 250}]}>
{/*<MapView
provider={PROVIDER_GOOGLE}
style={{flex: 1}}
region={{
latitude: Number(itemData.coordinate[0]),
longitude: Number(itemData.coordinate[1]),
latitudeDelta: 0.00864195044303443,
longitudeDelta: 0.000142817690068,
}}>
<MapView.Marker
coordinate={itemData.coordinate}
image={require('../../assets/images/map_marker.png')}
/>
</MapView>*/}
</View>
</ImageHeaderScrollView>
</View>
);
}
};
export default CardItemDetails;
const styles = StyleSheet.create({
container: {
flex: 1,
},
image: {
height: MAX_HEIGHT,
width: Dimensions.get('window').width,
alignSelf: 'stretch',
resizeMode: 'cover',
},
title: {
fontSize: 20,
},
name: {
fontWeight: 'bold',
},
section: {
padding: 20,
borderBottomWidth: 1,
borderBottomColor: '#cccccc',
backgroundColor: 'white',
},
sectionTitle: {
fontSize: 18,
fontWeight: 'bold',
},
sectionContent: {
fontSize: 16,
textAlign: 'justify',
},
categories: {
flexDirection: 'row',
justifyContent: 'flex-start',
alignItems: 'flex-start',
flexWrap: 'wrap',
},
categoryContainer: {
flexDirection: 'row',
backgroundColor: '#FF6347',
borderRadius: 20,
margin: 10,
padding: 10,
paddingHorizontal: 15,
},
category: {
fontSize: 14,
color: '#fff',
marginLeft: 10,
},
titleContainer: {
flex: 1,
alignSelf: 'stretch',
justifyContent: 'center',
alignItems: 'center',
},
imageTitle: {
color: 'white',
backgroundColor: 'transparent',
fontSize: 24,
},
navTitleView: {
height: MIN_HEIGHT,
justifyContent: 'center',
alignItems: 'center',
paddingTop: Platform.OS === 'ios' ? 40 : 5,
opacity: 0,
},
navTitle: {
color: 'white',
fontSize: 18,
backgroundColor: 'transparent',
},
sectionLarge: {
minHeight: 300,
},
});