代码之家  ›  专栏  ›  技术社区  ›  BeniaminoBaggins

withnavigation只能在导航器的视图层次结构上使用

  •  1
  • BeniaminoBaggins  · 技术社区  · 6 年前

    我得到错误:

    固定冲突: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)
    

    我已将我的vepo组件更改为该组件以实现Vahissan的答案:

    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
    

    没有错误,但警报模式不再显示

    2 回复  |  直到 6 年前
        1
  •  5
  •   vahissan    6 年前

    在react导航中,主stacknavigator创建一个上下文提供程序, navigation 如果使用上下文使用者,那么prop将对组件树中低于其级别的任何组件可用。

    两种方式访问 航行 prop using context consumer是将组件添加到stacknavigator,或者使用 withNavigation 功能。但是,由于react的上下文API的工作方式,任何使用 导航 函数必须位于组件树中StackNavigator的下方。

    如果您仍想访问 航行 无论组件树中的位置如何,您都必须将对stacknavigator的引用存储在模块中。遵循React导航的指南将帮助您做到这一点 https://reactnavigation.org/docs/en/navigating-without-navigation-prop.html

        2
  •  0
  •   BeniaminoBaggins    6 年前

    Vahissan的答案是正确的,但由于我的代码与 https://reactnavigation.org/docs/en/navigating-without-navigation-prop.html 就像我的stacknavigator不是组件一样,它只是一个对象。

    我所做的就是 AlertModal 组件将是StackNavigator的子级,从而接收 navigation 通过添加到我的 StackNavigator 的ContentComponent。代码如上所述,但在 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>
    )