我遇到了错误:
不变违反:withNavigation只能在视图上使用 导航器的层次结构。包装的组件无法获取 从道具或上下文访问导航
我不知道为什么,因为我在我的应用程序的其他组件中使用了withNavigation
,并且可以正常工作。我看不到导致错误的组件的差异。
代码:
组件:
const mapStateToProps = (state: State): Object => ({
alertModal: state.formControls.alertModal
})
const mapDispatchToProps = (dispatch: Dispatch<*>): Object => {
return bindActionCreators(
{
updateAlertModalHeight: updateAlertModalHeight,
updateAlertModalIsOpen: updateAlertModalIsOpen,
updateHasYesNo: updateAlertModalHasYesNo
},
dispatch
)
}
class AlertModalView extends Component<AlertModalProps, State> {
render(): Node {
return (
<View style={alertModalStyle.container}>
<PresentationalModal
style={presentationalModalStyle}
isOpen={this.props.alertModal.isOpen}
title={this.props.alertModal.title}
navigation={this.props.navigation}
updateHasYesNo={this.props.updateHasYesNo}
message={this.props.alertModal.message}
updateAlertModalHeight={this.props.updateAlertModalHeight}
viewHeight={this.props.alertModal.viewHeight}
hasYesNo={this.props.alertModal.hasYesNo}
yesClicked={this.props.alertModal.yesClicked}
updateAlertModalIsOpen={this.props.updateAlertModalIsOpen}
/>
</View>
)
}
}
// $FlowFixMe
const AlertModalViewComponent = connect(
mapStateToProps,
mapDispatchToProps
)(AlertModalView)
export default withNavigation(AlertModalViewComponent)
stackNavigator:
import React from 'react'
import { View, SafeAreaView } from 'react-native'
import Icon from 'react-native-vector-icons/EvilIcons'
import Add from '../product/add/view'
import Login from '../user/login/view'
import Search from '../product/search/query/view'
import { Image } from 'react-native'
import { StackNavigator, DrawerNavigator, DrawerItems } from 'react-navigation'
const AddMenuIcon = ({ navigate }) => (
<View>
<Icon
name="plus"
size={30}
color="#FFF"
onPress={() => navigate('DrawerOpen')}
/>
</View>
)
const SearchMenuIcon = ({ navigate }) => (
<Icon
name="search"
size={30}
color="#FFF"
onPress={() => navigate('DrawerOpen')}
/>
)
const Stack = {
Login: {
screen: Login
},
Search: {
screen: Search
},
Add: {
screen: Add
}
}
const DrawerRoutes = {
Login: {
name: 'Login',
screen: Login
},
'Search Vegan': {
name: 'Search',
screen: StackNavigator(Stack.Search, {
headerMode: 'none'
}),
navigationOptions: ({ navigation }) => ({
drawerIcon: SearchMenuIcon(navigation)
})
},
'Add vegan': {
name: 'Add',
screen: StackNavigator(Stack.Add, {
headerMode: 'none'
}),
navigationOptions: ({ navigation }) => ({
drawerIcon: AddMenuIcon(navigation)
})
}
}
const CustomDrawerContentComponent = props => (
<SafeAreaView style={{ flex: 1, backgroundColor: '#3f3f3f', color: 'white' }}>
<View>
<Image
style={{
marginLeft: 20,
marginBottom: 0,
marginTop: 0,
width: 100,
height: 100,
resizeMode: 'contain'
}}
square
source={require('../../images/logo_v_white.png')}
/>
</View>
<DrawerItems {...props} />
</SafeAreaView>
)
const Menu = StackNavigator(
{
Drawer: {
name: 'Drawer',
screen: DrawerNavigator(DrawerRoutes, {
initialRouteName: 'Login',
drawerPosition: 'left',
contentComponent: CustomDrawerContentComponent,
contentOptions: {
activeTintColor: '#27a562',
inactiveTintColor: 'white',
activeBackgroundColor: '#3a3a3a'
}
})
}
},
{
headerMode: 'none',
initialRouteName: 'Drawer'
}
)
export default Menu
在这里,我在应用程序组件中渲染StackNavigator
的{{1}}:
Menu
和我的根组件:
import React, { Component } from 'react'
import Menu from './menu/view'
import Props from 'prop-types'
import { Container } from 'native-base'
import { updateAlertModalIsOpen } from './formControls/alertModal/action'
import AlertModalComponent from './formControls/alertModal/view'
import UserLoginModal from './user/login/loginModal/view'
class Vepo extends Component {
componentDidMount() {
const { store } = this.context
this.unsubscribe = store.subscribe(() => {})
store.dispatch(this.props.fetchUserGeoCoords())
store.dispatch(this.props.fetchSearchQueryPageCategories())
store.dispatch(this.props.fetchCategories())
}
componentWillUnmount() {
this.unsubscribe()
}
render(): Object {
return (
<Container>
<Menu store={this.context} />
<AlertModalComponent
yesClicked={() => {
updateAlertModalIsOpen(false)
}}
/>
<UserLoginModal />
</Container>
)
}
}
Vepo.contextTypes = {
store: Props.object
}
export default Vepo
我已将Vepo组件更改为此,以实现vahissan的答案:
export const store = createStore(
rootReducer,
vepo,
composeWithDevTools(applyMiddleware(createEpicMiddleware(rootEpic)))
)
import NavigationService from './navigationService'
export const App = () => (
<Provider store={store}>
<Vepo
fetchUserGeoCoords={fetchUserGeoCoords}
fetchSearchQueryPageCategories={fetchSearchQueryPageCategories}
fetchCategories={fetchCategories}
/>
</Provider>
)
AppRegistry.registerComponent('vepo', () => App)
没有错误,但是alertModal不再显示
答案 0 :(得分:6)
在react-navigation中,主StackNavigator创建一个上下文提供程序,如果navigation
属性使用上下文使用者,则将使其对组件树中其级别以下的任何组件可用。
使用上下文使用者访问navigation
道具的两种方法是将组件添加到StackNavigator,或使用withNavigation
函数。但是,由于React的上下文API的工作原理,任何使用withNavigation
函数的组件都必须在组件树中的StackNavigator下方。
如果无论组件树中的位置如何,仍要访问navigation
属性,则必须将引用存储到模块中的StackNavigator。遵循反应导航指南将帮助您https://reactnavigation.org/docs/en/navigating-without-navigation-prop.html
答案 1 :(得分:4)
如果您使用的是react-navigation版本5,请将useNavigation挂钩与功能组件一起使用。该挂钩将导航对象注入到功能组件中。这是文档的链接:
答案 2 :(得分:0)
Vahissan的答案是正确的,但由于与https://reactnavigation.org/docs/en/navigating-without-navigation-prop.html的代码存在各种差异,例如stackNavigator不是组件,它只是一个对象,所以我无法使它起作用。
我要做的就是让AlertModal
组件成为stackNavigator的子组件,并通过将其添加到navigation
的ContentComponent中来接收StackNavigator
道具。代码如上所述,但是将CustomDrawerContentComponent
修改为这样:
const CustomDrawerContentComponent = props => (
<SafeAreaView style={{ flex: 1, backgroundColor: '#3f3f3f', color: 'white' }}>
<View>
<Image
style={{
marginLeft: 20,
marginBottom: 0,
marginTop: 0,
width: 100,
height: 100,
resizeMode: 'contain'
}}
square
source={require('../../images/logo_v_white.png')}
/>
</View>
<DrawerItems {...props} />
<AlertModalComponent
yesClicked={() => {
updateAlertModalIsOpen(false)
}}
/>
</SafeAreaView>
)
答案 3 :(得分:0)
对于任何可能感兴趣的人,您需要 npm install @react-navigation/native @react-navigation/compat @react-navigation/stack 以便 withNavigation 在最新版本中工作