エラーが発生しています:
不変違反: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
である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
そして私のルートコンポーネント:
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)
Vahissanによる回答を実装するために、Vepoコンポーネントをこれに変更しました。
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'
import NavigationService from './navigationService'
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}
ref={navigatorRef => {
NavigationService.setTopLevelNavigator(navigatorRef)
}}>
<AlertModalComponent
yesClicked={() => {
updateAlertModalIsOpen(false)
}}
/>
</Menu>
<UserLoginModal />
</Container>
)
}
}
Vepo.contextTypes = {
store: Props.object
}
export default Vepo
エラーはありませんが、alertModalは表示されなくなりました
反応ナビゲーションでは、メインのStackNavigatorがコンテキストプロバイダーを作成し、コンテキストコンシューマーを使用する場合、navigation
プロパティがコンポーネントツリー内のそのレベルより下のすべてのコンポーネントで使用可能になります。
コンテキストコンシューマを使用してnavigation
プロパティにアクセスする2つの方法は、StackNavigatorにコンポーネントを追加するか、withNavigation
関数を使用することです。ただし、ReactのコンテキストAPIの動作方法のため、withNavigation
関数を使用するコンポーネントは、コンポーネントツリーのStackNavigatorの下になければなりません。
コンポーネントツリー内の位置に関係なくnavigation
propにアクセスしたい場合は、モジュール内のStackNavigatorへの参照を保存する必要があります。 react-navigationのガイドに従うと、そのために役立ちます https://reactnavigation.org/docs/en/navigating-without-navigation-prop.html
Vahissanの答えは正しいですが、 https://reactnavigation.org/docs/en/navigating-without-navigation-prop.html と私のstackNavigatorのようなコードのさまざまな違いのため、私はそれを動作させることができませんでしたコンポーネントではなく、単なるオブジェクトです。
どうにかしてAlertModal
コンポーネントをstackNavigatorの子にし、navigation
のContentComponentに追加することでStackNavigator
propを受け取りました。コードは上記のとおりですが、CustomDrawerContentComponent
をintにすると、次のようになります。
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>
)