如何根据前一个道具渲染屏幕?
How to render a screen based on the props from the previous one?
我正在创建一个应用程序,其中有一个屏幕 (SpotMapScreen),根据所选 'tab',我在该屏幕上显示地图或列表视图上的“地点”。用户可以通过单击顶部选项卡之一更改显示系统:
我还想让用户可以通过单击上一个屏幕(开始屏幕)中的适当按钮来打开某个选项卡:
因此,当用户单击上述按钮之一并打开下一个屏幕 (SpotMapScreen) 时,我将传递参数 'active':
<TouchableOpacity
style={styles.button}
onPress={() => this.props.navigation.navigate('SpotMap', { active: 'map' })}
>
<Image style={[styles.sportIcon]}
source={require('../assets/images/ic_choose_relation.png')}/>
<Text
style={styles.buttonText}>{translate('startAct.btn_map')}</Text>
</TouchableOpacity>
<View style={styles.verticalDivision}/>
<TouchableOpacity
style={styles.button}
onPress={() => this.props.navigation.navigate('SpotMap', { active: 'list' })}
>
<Image style={[styles.sportIcon]}
source={require('../assets/images/ic_choose_organized.png')}/>
<Text
style={styles.buttonText}>{translate('startAct.btn_list')}</Text>
</TouchableOpacity>
在 SpotMapScreen 上,我从构造函数中的道具获取此参数:
constructor(props) {
super(props)
this.mapSupplier = new MapSupplier()
this.mapSupplier.setMyLocation(mock.myLocation)
this.state = {
myLocation: mock.myLocation,
active: props.navigation.state.params.active,
filters: {},
spots: [],
addNewSpotModeEnabled: true,
newSpotMarker: null,
}
}
我正在根据这个 'active' 变量渲染整个屏幕:
render() {
const active = this.state.active
if (active === 'map') {
return (
<SafeAreaView style={styles.container}>
{this.renderTabs(active)}
{this.renderMap()}
{this.renderActionButton()}
</SafeAreaView>
)
} else {
return (
<SafeAreaView style={styles.container}>
<ScrollView>
{this.renderTabs(active)}
{this.renderList()}
</ScrollView>
</SafeAreaView>
)
}
}
}
并且用户可以通过单击特定选项卡来更改显示外观:
handleTab = (tabKey) => {
this.setState({ active: tabKey })
}
renderTabs(active) {
const openMenu = () => {
this.props.navigation.openDrawer()
}
return (
<SafeAreaView style={styles.tabs}>
<View style={{ flex: 0.6, alignItems: 'center', justifyContent: 'center' }}>
<MaterialIcons name='menu' onPress={openMenu} size={18} style={{ alignSelf: 'center', paddingBottom: 10 }}/>
</View>
<View style={[styles.tab, active === 'map' ? styles.activeTab : null]}>
<Feather name="map-pin" color={colors.black} size={18}
style={{ paddingBottom: 10, alignSelf: 'center', justifyContent: 'center' }}/>
<Text style={[styles.tabTitle, active === 'map' ? styles.activeTabTitle : null]}
onPress={() => this.handleTab('map')}>
{translate('mapAct.map')}
</Text>
</View>
<View style={[styles.tab, active === 'list' ? styles.activeTab : null]}>
<Feather name="list" color={colors.black} size={18}
style={{ paddingBottom: 10, alignSelf: 'center', justifyContent: 'center' }}/>
<Text style={[styles.tabTitle, active === 'list' ? styles.activeTabTitle : null]}
onPress={() => this.handleTab('list')}>
{translate('mapAct.list')}
</Text>
</View>
<View style={{ flex: 0.6, alignItems: 'center', justifyContent: 'center' }}>
<MaterialIcons name='filter-list' onPress={() => this.props.navigation.navigate('Filters')} size={18}
style={{ alignSelf: 'center', paddingBottom: 10 }}/>
</View>
</SafeAreaView>
)
}
但这是我的问题,此解决方案仅适用于首次使用屏幕。当用户返回 StartScreen 并单击其中一个按钮时,不会调用下一个屏幕 (SpotMap) 中的构造函数,因此不会打开正确的选项卡。
我如何才能在每次打开下一个屏幕时从 StartScreen 接收道具,而不仅仅是第一次(更像是 android OnResume() 而不是 OnCreate())。我读到我可以使用 componentDidMount()
方法,但它对我不起作用,可能是因为我使用的是 async componentDidMount()
方法版本?
非常感谢你的帮助。
我发布了我自己问题的解决方案,因为我终于找到了。如果你想在每次“恢复”屏幕并且你正在使用 async componentDidMount()
时以 react-native 从上一个屏幕获取道具,你应该重写方法 componentDidUpdate(prevProps, prevState)
。我将下面的代码添加到“SpotMapScreen”,现在它在我的问题中按预期工作:
componentDidUpdate(prevProps, prevState) {
let new_active = 'map'
if (typeof this.props.navigation.state.params != "undefined"){
new_active = this.props.navigation.state.params.active
}
if (prevState.active !== new_active) {
this.setState({
active: new_active,
})
}
}
我正在创建一个应用程序,其中有一个屏幕 (SpotMapScreen),根据所选 'tab',我在该屏幕上显示地图或列表视图上的“地点”。用户可以通过单击顶部选项卡之一更改显示系统:
我还想让用户可以通过单击上一个屏幕(开始屏幕)中的适当按钮来打开某个选项卡:
因此,当用户单击上述按钮之一并打开下一个屏幕 (SpotMapScreen) 时,我将传递参数 'active':
<TouchableOpacity
style={styles.button}
onPress={() => this.props.navigation.navigate('SpotMap', { active: 'map' })}
>
<Image style={[styles.sportIcon]}
source={require('../assets/images/ic_choose_relation.png')}/>
<Text
style={styles.buttonText}>{translate('startAct.btn_map')}</Text>
</TouchableOpacity>
<View style={styles.verticalDivision}/>
<TouchableOpacity
style={styles.button}
onPress={() => this.props.navigation.navigate('SpotMap', { active: 'list' })}
>
<Image style={[styles.sportIcon]}
source={require('../assets/images/ic_choose_organized.png')}/>
<Text
style={styles.buttonText}>{translate('startAct.btn_list')}</Text>
</TouchableOpacity>
在 SpotMapScreen 上,我从构造函数中的道具获取此参数:
constructor(props) {
super(props)
this.mapSupplier = new MapSupplier()
this.mapSupplier.setMyLocation(mock.myLocation)
this.state = {
myLocation: mock.myLocation,
active: props.navigation.state.params.active,
filters: {},
spots: [],
addNewSpotModeEnabled: true,
newSpotMarker: null,
}
}
我正在根据这个 'active' 变量渲染整个屏幕:
render() {
const active = this.state.active
if (active === 'map') {
return (
<SafeAreaView style={styles.container}>
{this.renderTabs(active)}
{this.renderMap()}
{this.renderActionButton()}
</SafeAreaView>
)
} else {
return (
<SafeAreaView style={styles.container}>
<ScrollView>
{this.renderTabs(active)}
{this.renderList()}
</ScrollView>
</SafeAreaView>
)
}
} }
并且用户可以通过单击特定选项卡来更改显示外观:
handleTab = (tabKey) => {
this.setState({ active: tabKey })
}
renderTabs(active) {
const openMenu = () => {
this.props.navigation.openDrawer()
}
return (
<SafeAreaView style={styles.tabs}>
<View style={{ flex: 0.6, alignItems: 'center', justifyContent: 'center' }}>
<MaterialIcons name='menu' onPress={openMenu} size={18} style={{ alignSelf: 'center', paddingBottom: 10 }}/>
</View>
<View style={[styles.tab, active === 'map' ? styles.activeTab : null]}>
<Feather name="map-pin" color={colors.black} size={18}
style={{ paddingBottom: 10, alignSelf: 'center', justifyContent: 'center' }}/>
<Text style={[styles.tabTitle, active === 'map' ? styles.activeTabTitle : null]}
onPress={() => this.handleTab('map')}>
{translate('mapAct.map')}
</Text>
</View>
<View style={[styles.tab, active === 'list' ? styles.activeTab : null]}>
<Feather name="list" color={colors.black} size={18}
style={{ paddingBottom: 10, alignSelf: 'center', justifyContent: 'center' }}/>
<Text style={[styles.tabTitle, active === 'list' ? styles.activeTabTitle : null]}
onPress={() => this.handleTab('list')}>
{translate('mapAct.list')}
</Text>
</View>
<View style={{ flex: 0.6, alignItems: 'center', justifyContent: 'center' }}>
<MaterialIcons name='filter-list' onPress={() => this.props.navigation.navigate('Filters')} size={18}
style={{ alignSelf: 'center', paddingBottom: 10 }}/>
</View>
</SafeAreaView>
)
}
但这是我的问题,此解决方案仅适用于首次使用屏幕。当用户返回 StartScreen 并单击其中一个按钮时,不会调用下一个屏幕 (SpotMap) 中的构造函数,因此不会打开正确的选项卡。
我如何才能在每次打开下一个屏幕时从 StartScreen 接收道具,而不仅仅是第一次(更像是 android OnResume() 而不是 OnCreate())。我读到我可以使用 componentDidMount()
方法,但它对我不起作用,可能是因为我使用的是 async componentDidMount()
方法版本?
非常感谢你的帮助。
我发布了我自己问题的解决方案,因为我终于找到了。如果你想在每次“恢复”屏幕并且你正在使用 async componentDidMount()
时以 react-native 从上一个屏幕获取道具,你应该重写方法 componentDidUpdate(prevProps, prevState)
。我将下面的代码添加到“SpotMapScreen”,现在它在我的问题中按预期工作:
componentDidUpdate(prevProps, prevState) {
let new_active = 'map'
if (typeof this.props.navigation.state.params != "undefined"){
new_active = this.props.navigation.state.params.active
}
if (prevState.active !== new_active) {
this.setState({
active: new_active,
})
}
}