Ошибка: не определен маршрут для ключа «Добавить товар». Должно быть одно из: стековых действий экрана

Я следую этому SO-ответу - я просто пытаюсь сбросить стек при навигации, чтобы мой компонент отключился, когда уйти, потому что мне нужно componentDidMount, чтобы выстрелить при навигации к нему.

Я хочу уйти от этого:

const navigateAction = NavigationActions.navigate({
  routeName: route
})
props.navigation.dispatch(navigateAction)

к этому:

const resetAction = StackActions.reset({
  index: 0,
  actions: [NavigationActions.navigate({ routeName: route })],
})
props.navigation.dispatch(resetAction)

Но когда я это сделаю, я получаю эту ошибку:

Ошибка: не определен маршрут для ключа «Добавить товар». Должно быть одно из: стековых действий экрана

Это полная функция, в которой находится приведенный выше код:

  navigateToScreen = (route, props, headingKey: string) => () => {
    if (this.props.navigationProps.activeItemKey !== headingKey) {
      this.setState({ activeSections: [] })
    }
    // const navigateAction = NavigationActions.navigate({
    //   routeName: route
    // })
    
    const resetAction = StackActions.reset({
      index: 0,
      actions: [NavigationActions.navigate({ routeName: route })],
    })
    props.navigation.dispatch(resetAction)
  }

Вот мои маршруты навигации:

export const AddMenuIcon = ({ navigate }: NavigateType) => (
  <View>
    <Icon
      name="plus"
      size={25}
      color="#FFF"
      onPress={() => navigate('DrawerOpen')}
    />
  </View>
)

export const SearchMenuIcon = ({ navigate }: NavigateType) => (
  <Icon
    name="search"
    size={25}
    color="#FFF"
    onPress={() => navigate('DrawerOpen')}
  />
)

export const Stack = {
  Login: {
    screen: Login
  },
  Search: {
    screen: Search
  },
  AddGroceryItem: {
    screen: AddGroceryItem
  },
  AddGroceryStore: {
    screen: AddGroceryStore
  }
}

export const DrawerRoutes = {
  Login: {
    name: 'Login',
    screen: Login
  },
  'Find Vegan': {
    name: 'Search',
    screen: createStackNavigator(Stack.Search, {
      headerMode: 'none'
    }),
    navigationOptions: ({ navigation }: NavigationType) => ({
      drawerIcon: SearchMenuIcon(navigation)
    })
  },
  'Add Grocery Item': {
    name: 'Add',
    screen: createStackNavigator(Stack.AddGroceryItem, {
      headerMode: 'none'
    }),
    navigationOptions: ({ navigation }: NavigationType) => ({
      drawerIcon: AddMenuIcon(navigation)
    })
  },
  'Add Grocery Store': {
    name: 'AddGroceryStore',
    screen: createStackNavigator(Stack.AddGroceryStore, {
      headerMode: 'none'
    }),
    navigationOptions: ({ navigation }: NavigationType) => ({
      drawerIcon: AddMenuIcon(navigation)
    })
  }
}

export const sections = [
  {
    mainHeading: 'Login',
    navigationPath: 'Login',
    icon: 'user-circle'
  },
  {
    mainHeading: 'Find Vegan',
    navigationPath: 'Find Vegan',
    icon: 'search'
  },
  {
    mainHeading: 'Add Vegan',
    subOptions: [
      {
        secondaryHeading: 'Grocery Items',
        mainHeading: 'Add Vegan',
        secondaryHeadingKey: 'Add Grocery Item',
        navigationPath: 'Add Grocery Item',
        icon: { name: 'shopping-basket', color: Colors.white }
      },
      {
        secondaryHeading: 'Grocery Stores',
        mainHeading: 'Add Vegan',
        secondaryHeadingKey: 'Add Grocery Itemx',
        navigationPath: 'Add Grocery Store',
        icon: { name: 'shopping-cart', color: Colors.white }
      },
      {
        secondaryHeading: 'Restaurant Meals',
        mainHeading: 'Add Vegan',
        secondaryHeadingKey: 'Add Grocery Itemx',
        navigationPath: 'Add Grocery Item',
        icon: { name: 'utensils', color: Colors.white }
      },
      {
        secondaryHeading: 'Restaurants',
        mainHeading: 'Add Vegan',
        secondaryHeadingKey: 'Add Grocery Itemx',
        navigationPath: 'Add Grocery Item',
        icon: { name: 'store-alt', color: Colors.white }
      },
      {
        secondaryHeading: 'Events',
        mainHeading: 'Add Vegan',
        secondaryHeadingKey: 'Add Grocery Itemx',
        navigationPath: 'Add Grocery Item',
        icon: { name: 'calendar-alt', color: Colors.white }
      },
      {
        secondaryHeading: 'Fashion',
        mainHeading: 'Add Vegan',
        secondaryHeadingKey: 'Add Grocery Itemx',
        navigationPath: 'Add Grocery Item',
        icon: { name: 'tshirt', color: Colors.white }
      }
    ],
    icon: 'plus-circle'
  }
]

Вот мой компонент полного меню, в котором есть меню навигации.

class AccordionView extends React.Component<AccordianProps, AccordianState> {
  state = {
    activeSections: [],
    sections: Data.sections
  }

  getParentLabelStyle = (mainHeading: string) => {
    if (this.props.navigationProps.activeItemKey === mainHeading) {
      return { ...Typography.whiteLabel, color: Colors.green_lite_2 }
    }
    const sectionFromSubOption = this.state.sections.find(
      (x) =>
        x.subOptions &&
        x.subOptions.find(
          (y) =>
            y.secondaryHeadingKey === this.props.navigationProps.activeItemKey
        )
    )
    if (
      sectionFromSubOption &&
      sectionFromSubOption.mainHeading === mainHeading
    ) {
      return { ...Typography.whiteLabel, color: Colors.green_lite_2 }
    } else {
      return Typography.whiteLabel
    }
  }

  getParentIconColor = (mainHeading: string) => {
    if (this.props.navigationProps.activeItemKey === mainHeading) {
      return Colors.green_lite_2
    }
    const sectionFromSubOption = this.state.sections.find(
      (x) =>
        x.subOptions &&
        x.subOptions.find(
          (y) =>
            y.secondaryHeadingKey === this.props.navigationProps.activeItemKey
        )
    )
    if (
      sectionFromSubOption &&
      sectionFromSubOption.mainHeading === mainHeading
    ) {
      return Colors.green_lite_2
    } else {
      return Colors.white
    }
  }

  getLabelStyle = (headingKey: string) => {
    if (this.props.navigationProps.activeItemKey === headingKey) {
      return { ...Typography.whiteLabel, color: Colors.green_lite_2 }
    } else {
      return Typography.whiteLabel
    }
  }

  getIconColor = (headingKey: string): string => {
    if (this.props.navigationProps.activeItemKey === headingKey) {
      return Colors.green_lite_2
    } else {
      return Colors.white
    }
  }

  updateSections = (activeSections) => {
    this.setState({ activeSections })
  }

  navigateToScreen = (route, props, headingKey: string) => () => {
    if (this.props.navigationProps.activeItemKey !== headingKey) {
      this.setState({ activeSections: [] })
    }
    // const navigateAction = NavigationActions.navigate({
    //   routeName: route
    // })
    
    const resetAction = StackActions.reset({
      index: 0,
      actions: [NavigationActions.navigate({ routeName: route })],
    })
    props.navigation.dispatch(resetAction)
  }

  renderSectionTitle = () => {
    return <View />
  }

  renderHeader = (section, userName?: string) => {
    return (
      <View>
        {section.navigationPath && (
          <TouchableOpacity
            onPress={this.navigateToScreen(
              section.navigationPath,
              this.props.navigationProps
            )}>
            <View style={styles.subMenuItemContainer}>
              <AwesomeIcon
                style={styles.icon}
                name={section.icon}
                light
                size={25}
                color={this.getParentIconColor(section.mainHeading)}
              />
              <Text
                style={{ ...this.getParentLabelStyle(section.mainHeading) }}>
                {userName ? userName : section.mainHeading}
              </Text>
            </View>
          </TouchableOpacity>
        )}
        {section.subOptions && (
          <View style={styles.subMenuItemContainer}>
            <AwesomeIcon
              style={styles.icon}
              name={section.icon}
              size={25}
              light
              color={this.getParentIconColor(section.mainHeading)}
            />
            <Text style={{ ...this.getParentLabelStyle(section.mainHeading) }}>
              {section.mainHeading}
            </Text>
          </View>
        )}
      </View>
    )
  }

  renderContent = (section) => {
    return (
      section.subOptions &&
      section.subOptions.map(
        (item) =>
          item.secondaryHeading === 'Grocery Items' ? (
            <TouchableOpacity
              onPress={this.navigateToScreen(
                item.navigationPath,
                this.props.navigationProps,
                item.secondaryHeadingKey
              )}>
              <View style={{...styles.parentMenuItemContainer, marginLeft: -20}}>
                <AwesomeIcon
                  style={styles.icon}
                  size={25}
                  light
                  name={item.icon.name}
                  color={this.getIconColor(item.secondaryHeadingKey)}
                />
                <Text
                  style={{ ...this.getLabelStyle(item.secondaryHeadingKey) }}>
                  {item.secondaryHeading}
                </Text>
              </View>
            </TouchableOpacity>
          ) : (
            <View style={{...styles.parentMenuItemContainer, marginLeft: -20}}>
              <AwesomeIcon
                style={styles.icon}
                size={25}
                light
                name={item.icon.name}
                color={'#969696'}
              />
              <Text
                style={{ ...this.getLabelStyle(item.secondaryHeadingKey), color: '#969696' }}>
                {item.secondaryHeading}
              </Text>
              <Text
                style={{ ...this.getLabelStyle(item.secondaryHeadingKey), fontSize: 12, paddingLeft: 0, color: 'red' }}>
                (coming soon)
              </Text>
            </View>

          )
      )
    )
  }

  render() {
    return (
      <Accordion
        sections={this.state.sections}
        activeSections={this.state.activeSections}
        renderSectionTitle={this.renderSectionTitle}
        renderHeader={(section) => {
          let userName
          if (section.mainHeading === 'Login') {
            const loginItem = this.props?.navigationProps?.items?.find(
              (x) => x.key === 'Login'
            )
            userName = loginItem?.params?.userFirstName
          }
          return this.renderHeader(section, userName)
        }}
        renderContent={this.renderContent}
        onChange={this.updateSections}
      />
    )
  }
}

export class CustomDrawerContentComponent extends React.Component<
  AccordianProps,
  AccordianState
> {
  state = {}
  render() {
    return (
      <SafeAreaView style={styles.menuContainer}>
        <View style={styles.vepoImageContainer}>
          <Image
            style={styles.vepoImage}
            square
            source={require('src/images/logo_v_white.png')}
          />
        </View>

        <Text style={styles.mottoText}>Find Every Vegan Thing!</Text>
        <View style={styles.accordianContainer}>
          <AccordionView navigationProps={this.props} />
        </View>

        <AlertModalComponent
          yesClicked={() => {
            updateAlertModalIsOpen(false)
          }}
        />
      </SafeAreaView>
    )
  }
}
const { width, height } = Dimensions.get('screen')

let Menu = createStackNavigator(
  {
    Drawer: {
      name: 'Drawer',
      screen: createDrawerNavigator(Data.DrawerRoutes, {
        initialRouteName: 'Login',
        drawerPosition: 'left',
        drawerWidth: Math.min(height, width),
        contentComponent: CustomDrawerContentComponent,
        contentOptions: {
          activeTintColor: '#27a562',
          inactiveTintColor: 'white',
          activeBackgroundColor: '#3a3a3a'
        }
      })
    }
  },
  {
    headerMode: 'none',
    initialRouteName: 'Drawer'
  }
)

const menuItemContainer = {
  display: 'flex',
  flexDirection: 'row',
  height: 50,
  alignItems: 'center',
  borderBottomWidth: Borders.thinBorder,
  borderBottomColor: Colors.grey_dk_2
}

const styles = {
  vepoImage: {
    marginLeft: Spacing.sm_4,
    marginBottom: Spacing.none,
    marginTop: Spacing.md_2,
    width: 120,
    height: Distances.FormElementHeights.Double,
    resizeMode: 'contain'
  },
  accordianContainer: {
    borderTopWidth: Borders.thinBorder,
    borderTopColor: Colors.grey_dk_2
  },
  mottoText: { ...Typography.whiteLabel, marginBottom: Spacing.md_4 },
  vepoImageContainer: {
    marginBottom: Spacing.md_4
  },
  menuContainer: {
    flex: 1,
    backgroundColor: Colors.grey_dk_3,
    color: Colors.white
  },
  icon: {
    marginLeft: Spacing.md_4,
    width: 30
  },
  subMenuItemContainer: menuItemContainer,
  parentMenuItemContainer: {
    ...menuItemContainer,
    paddingLeft: Spacing.lg_7
  }
}

// $FlowFixMe
Menu = createAppContainer(Menu)

export default Menu

Как исправить эту ошибку?


person BeniaminoBaggins    schedule 23.07.2020    source источник


Ответы (1)


Похоже, вы переходите к свойству navigationPath каждого раздела, которое в данном случае вы определили как Add Grocery Item, тогда как фактический путь, по которому вы пытаетесь перейти, - AddGroceryItem.

person Kai    schedule 23.07.2020
comment
Спасибо. Чтобы проверить вашу теорию, я попытался жестко ее закодировать: actions: [NavigationActions.navigate({ routeName: 'AddGroceryItem' })] и получил ошибку: для ключа AddGroceryItem не определен маршрут. Должен быть одним из: screen. Так что я так не думаю (если я правильно вас понял). - person BeniaminoBaggins; 23.07.2020