使用参数反应本机导航到另一个堆栈

时间:2020-08-27 12:20:25

标签: react-native react-navigation

"code-runner.executorMap":{
    "cpp": "cd $dir && g++ -std=c++17 $fileName -o $fileNameWithoutExt && $dir$fileNameWithoutExt",
},

我想从import React from 'react'; import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'; import { enableScreens } from 'react-native-screens'; import { createNativeStackNavigator } from 'react-native-screens/native-stack'; enableScreens(); const Tab = createBottomTabNavigator(); const RootStack = createNativeStackNavigator(); const WardrobeStack = createNativeStackNavigator(); const OutfitStack = createNativeStackNavigator(); const CreateLookStack = createNativeStackNavigator(); const ProfileStack = createNativeStackNavigator(); export const WardrobeNavigator = () => { return ( <WardrobeStack.Navigator screenOptions={{ headerShown: false }} initialRouteName='Wardrobe'> <WardrobeStack.Screen name="Wardrobe" component={Wardrobe} /> // <== navigate to here with params <WardrobeStack.Screen name="Profile" component={Profile} /> <WardrobeStack.Screen name="AddFirstItem" component={AddFirstItem} /> <WardrobeStack.Screen name="RetakeContinue" component={RetakeContinue} /> <WardrobeStack.Screen name="CategoryBrand" component={CategoryBrand} /> <WardrobeStack.Screen name="DeleteCategory" component={DeleteCategory} /> </WardrobeStack.Navigator> ); } export const OutfitNavigator = () => { return ( <OutfitStack.Navigator screenOptions={{ headerShown: false }} initialRouteName='LookBook'> <OutfitStack.Screen name="Outfits" component={Outfits} /> <OutfitStack.Screen name="LookBook" component={LookBook} /> <OutfitStack.Screen name="LookBookList" component={LookBookList} /> // <== navigate from here <OutfitStack.Screen name="Profile" component={Profile} /> <OutfitStack.Screen name="ShoppingList" component={ShoppingList} /> </OutfitStack.Navigator> ); } export const CreateLookNavigator = () => { return ( <CreateLookStack.Navigator screenOptions={{ headerShown: false, }} initialRouteName="NewLook"> <CreateLookStack.Screen name="NewLook"> {props => ( <NewLook {...props} initialParams={{ lookSaveType: AppConstants.DEFAULT_LOOK_SAVE_TYPE, }} /> )} </CreateLookStack.Screen> <CreateLookStack.Screen name="SaveLook" component={SaveLook} /> </CreateLookStack.Navigator> ); } export const ProfileNavigator = () => { return ( <ProfileStack.Navigator screenOptions={{ headerShown: false }} initialRouteName='ProfileOnbarding'> <ProfileStack.Screen name="ProfileOnbarding" component={ProfileOnboarding} /> <ProfileStack.Screen name="ProfileAllSet" component={ProfileAllSet} /> </ProfileStack.Navigator> ); } export const RootNavigator = () => { return ( <RootStack.Navigator screenOptions={{ headerShown: false }} initialRouteName='Main' mode='modal'> <RootStack.Screen name="Main" component={BottomTabNavigator} /> <RootStack.Screen name="Brands" component={BrandStores} /> <RootStack.Screen name="ItemScreen" component={ItemScreen} /> <RootStack.Screen name="CreateLook" component={CreateLookNavigator} /> <RootStack.Screen name="ShoppingList" component={ShoppingList} /> <RootStack.Screen name="ProfileOnboarding" component={ProfileNavigator} /> {/* add full screen appear as modal */} </RootStack.Navigator> ); } export const BottomTabNavigator = () => { return ( <Tab.Navigator initialRouteName="Outfits" screenOptions={({ route }) => ({ tabBarIcon: ({ focused, color, size }) => { switch (route.name) { case 'Explore': return focused ? <ActiveTeleIcon /> : <InactiveTeleIcon /> case 'Bookings': return focused ? <ActiveBookingIcon /> : <InactiveBookingIcon /> case 'Wardrobe': return focused ? <ActiveWardrobeIcon /> : <InactiveWardrobeIcon /> case 'Outfits': return focused ? <ActiveOutfitsIcon /> : <InactiveOutfitsIcon /> case 'Chat': return focused ? <ActiveChatIcon /> : <InactiveChatIcon /> } }, })} tabBarOptions={{ activeTintColor: Colors.PRIMARY, inactiveTintColor: Colors.SECONDARY_TEXT, statusBarStyle: 'light-content', style: styles.tabContainer, labelStyle: styles.labelStyle, allowFontScaling: true, }} > <Tab.Screen name="Explore" component={Explore} options={{ tabBarLabel: 'Explore' }} /> <Tab.Screen name="Bookings" component={Bookings} options={{ tabBarLabel: 'Bookings', }} /> <Tab.Screen name="Wardrobe" component={WardrobeNavigator} options={{ tabBarLabel: 'Wardrobe', }} /> <Tab.Screen name="Outfits" component={OutfitNavigator} options={{ tabBarLabel: 'Outfits', }} /> <Tab.Screen name="Chat" component={Chat} options={{ tabBarLabel: 'Chat', }} /> </Tab.Navigator> ); }; 导航到LookBookList,这就是我在 lookbook-list.js 文件中所做的事情。

Wardrobe

我的 Wardrobe.js 文件:

  <HeaderBar
    backButton
    leftClick={() => navigation.goBack()}
    rightIcon={<HangerIcon />}
    rightIconClick={() => {
      navigation.navigate('Wardrobe', {openModal: true});
    }}
  />

我遇到以下错误:

export const Wardrobe = ({route}) => { console.log('route.params', route.params) // <== this is undefined ??? const {openModal} = route.params; const navigation = useNavigation(); const [isVisible, setIsVisible] = useState(openModal);

2 个答案:

答案 0 :(得分:1)

通过查看您的代码,我认为问题在于您还可以从标签页访问WardrobeNavigator,而不仅仅是从导航。由于您的初始屏幕是Wardrobe中的WardrobeNavigator,并且由于您没有通过initialParams,因此route.params.openModal会在导航中设置参数之前得到评估。

为了防止未定义它并提供默认值,我们可以使用以下语法:

const openModal = route.params?.openModal ?? false; // So false is the default value here

https://reactnavigation.org/docs/upgrading-from-4.x/#no-more-getparam

更新

它不起作用的原因是因为您要更新WardrobeNavigator而不是Wardrobe的参数。由于要将参数传递给嵌套屏幕,因此可以执行以下操作:

navigation.navigate('Wardrobe', {
  screen: 'Wardrobe',
  params: { openModal: true },
})

答案 1 :(得分:1)

所以我已经使用React的Context API解决了这个问题。

wardrobe-context.js 中创建了一个上下文:

import React, {useState} from 'react';

export const WardrobeContext = React.createContext();

function WardrobeProvider(props) {
  const [isAddItemModalOpen, setIsAddItemModalOpen] = useState(false);

  return (
    <WardrobeContext.Provider
      value={{isAddItemModalOpen, setIsAddItemModalOpen}}>
      {props.children}
    </WardrobeContext.Provider>
  );
}

export default WardrobeProvider;

navigation.js 文件中的文件,用WardrobeProvider包装了我的根导航堆栈:

export const RootNavigator = () => {
    return (
        <WardrobeProvider> // <== wrapper context provider
            <RootStack.Navigator
                screenOptions={{
                    headerShown: false
                }}
                initialRouteName='Main'
                mode='modal'>
                <RootStack.Screen name="Main" component={BottomTabNavigator} />
                <RootStack.Screen name="Brands" component={BrandStores} />
                <RootStack.Screen name="ItemScreen" component={ItemScreen} />
                <RootStack.Screen name="CreateLook" component={CreateLookNavigator} />
                <RootStack.Screen name="ShoppingList" component={ShoppingList} />
                <RootStack.Screen name="StylistInstructions" component={ProfileNavigator} />
                {/* add full screen appear as modal */}
            </RootStack.Navigator>
        </WardrobeProvider>
    );
}

最后,在 Wardrobe.js 中:

import React, { useState, useEffect, useContext } from 'react';
import { useFocusEffect } from '@react-navigation/native';
import { WardrobeContext } from '../../../context/wardrobe-context';
export const Wardrobe = () => {
    const {isAddItemModalOpen, setIsAddItemModalOpen} = useContext(WardrobeContext);

    const [isVisible, setIsVisible] = useState(false);

    useFocusEffect(
        React.useCallback(() => {
            setIsVisible(isAddItemModalOpen) // <== set value here to open modal
          return () => setIsAddItemModalOpen(false); // <== clear/reset the value on navigation change
        }, [isAddItemModalOpen])
    );

useFocusEffect用于设置isAddItemModalOpen屏幕聚焦时isVisible State的Wardrobe.js的值,而当屏幕聚焦时上下文中的值设置为false当用户导航到另一个屏幕时,没有聚焦。

lookbook-list.js 导航到 Wardrobe.js 来更新上下文值:

  import {WardrobeContext} from '../../../context/wardrobe-context';

  <HeaderBar
    backButton
    leftClick={() => navigation.goBack()}
    rightIcon={<HangerIcon />}
    rightClick={() => {
      wardrobeContext.setIsAddItemModalOpen(true); // <== update context here
      navigation.navigate('Wardrobe'); // <== and then navigate
    }}
  />

欢迎提出改进建议。谢谢