如何使用选项卡导航器将道具传递到 Screen 组件?

问题描述 投票:0回答:12

这是我在 StackOverflow 上的第一篇文章,如果我没有遵循正确的格式,请道歉。

我正在使用

tab navigator from React Navigation v 5.x
构建我的第一个应用程序,并且在将道具从一个屏幕传递到另一个屏幕时遇到了一个大问题

我想要实现的是:

  1. 更改我的一个屏幕中的数据列表。
  2. 这些更改会影响另一个屏幕上发生的情况。

我尝试过this(我未能设置要传递的道具),this(已弃用的react-navigation版本)和this(也是旧版本的react-navigation)。

和 Redux,但当前版本的 React 导航没有可用的示例。

我对此已经束手无策,真的需要一步一步地了解如何实现这一目标。 这是我想做的事情的粗略草图:

我的想法是通过回调将父状态作为 props 向下发送,但我找不到在最新版本的反应导航中通过屏幕组件发送 props 的方法...

这是我的导航设置:

const Tab = createBottomTabNavigator()

export default class MyApp extends Component{

    constructor(props) {
        super(props);
    }

    render(){
        return (
            <NavigationContainer>
                <Tab.Navigator 
                    screenOptions={({ route }) => ({
                        tabBarIcon: ({ focused, color, size }) => {
                            let iconName;

                            if (route.name === 'My tests') {
                                iconName = focused ? 'ios-list-box' : 'ios-list';
                            } else if (route.name === 'Testroom') {
                                iconName = focused ? 'ios-body' : 'ios-body';
                            }

                            return <Ionicons name={iconName} size={size} color={color} />;
                        },
                    })}
                    tabBarOptions={{
                        activeTintColor: 'tomato',
                        inactiveTintColor: 'gray',
                            
                    }}>

                    <Tab.Screen name="My tests"  component={MyTests}/> //This is where I want to send props
                    <Tab.Screen name="Testroom" component={TestRoom} />  //This is where I want to send props
                    
                </Tab.Navigator>
            </NavigationContainer>
        )
    }
}

我读过this,但这对我来说毫无意义。它如何适应组件树?什么去哪儿?请帮忙!

reactjs react-native react-redux parameter-passing react-props
12个回答
83
投票

您可以使用属性“children”来传递元素类型jsx,而不是属性“component”,这是react-native推荐的。

通过这种方式,您可以将 props 传递给组件示例:

    <tab.Screen
    name="home"
       children={()=><ComponentName propName={propValue}/>}
    />

需要使用'()=>',因为属性children需要一个返回jsx元素的函数,它是功能性的。


20
投票

查看代码注释中的答案。

<Tab.Screen
  name="AdminTab"
  children={() => <AdminPage userData={this.props.userSettings} />}
  // component={() => <AdminPage userData={this.props.userSettings} />} <<<---- Although this will work but passing an inline function will cause the component state to be lost on re-render and cause perf issues since it's re-created every render. You can pass the function as children to 'Screen' instead to achieve the desired behaviour. You can safely remove the component attribute post adding children.
/>

看起来您正在为屏幕“AdminTab”的“组件”道具传递一个内联函数(例如

component={() => <SomeComponent />
})。传递内联函数将导致组件状态在重新渲染时丢失,并导致性能问题,因为它会在每次渲染时重新创建。您可以将该函数作为子函数传递给“Screen”,以实现所需的行为。


17
投票

反应导航版本5+

<Tab.Screen name="Work" component={Works} initialParams={{ age: 45 }} />

可以使用

Works
组件上的道具进行访问。


9
投票

为了将 props 发送到

<MyTests />
组件,在
<Tab.Screen />
内部:

<Tab.Screen name="My tests">
  {() => <MyTests myPropsName={myPropsValue} />}
</Tab.Screen>

2
投票
<Tab.Navigator>
   <Tab.Screen name="Lead">
   {() => <LeadList {...this.props} />}
   </Tab.Screen>

   <Tab.Screen name="Opportunity">
   {() => <OpportunityList {...this.props} />}
   </Tab.Screen>
</Tab.Navigator>

2
投票

我还需要将一个函数传递到屏幕,以便在所有屏幕上渲染弹出窗口,但需要在特定屏幕上显示弹出窗口。这是我的解决方案。现在忘记重新渲染(性能)问题。

       <Tab.Screen
        initialParams={{
            onRemovePress: () => {
              props.setShowPopup(true)
            }
          }}
        name="Followers"
        component={Followers}
        options={{
          tabBarLabel: ({ focused, color }) => {
            return (
              <Text style={{ color: focused ? light.tintColor : light.black, marginBottom: 10 }}>{`${props.numOfFollowers} Followers`}</Text>
            )
          }
        }}
      />

0
投票

您可以使用以下

<Tab.Screen name="Favourite" component={() => <RecipeList CategoryId={0}></RecipeList>}/>

您可能会因重新渲染组件而发出当前状态丢失的警告。但道具会起作用。 如果你想复制当前状态道具,那么你可以使用 {...props}


0
投票
<Tab.Screen
   name='tabName'
   children={()=>{
    return(
      <CustomComponent prop={yourProp} />
    )
   }}
  />

今天第一次研究这个,发现它非常有帮助,只是想提供一些小更新,对于@react-navigation/bottom-tabs,v^5.11.10,您需要确保不再传递组件Tab.screen 中的 prop 并确保 Children 中的匿名函数返回一个元素/组件。


0
投票

如果您使用 ScreenMap 来渲染屏幕,您可以这样做:

_renderScene = SceneMap({
    first: () => <MyEvents {...this.props} date={this.state.date} />,
    second: () => <F4FEvents {...this.props} date={this.state.date} />,
});

0
投票

如果您从一个选项卡导航到另一个选项卡并且未更新,请尝试此方法,这会对您有所帮助

 <Tab.Screen
    name="Transaction"
    children={() => <GoldTransaction data={true} />}/>

0
投票

这在 JS 中有效,但在 TS 中无效。 因为 TS 期望类型来自属性“children”,该属性在此处声明为类型 孩子们:(道具:{ 路线:RouteProp; 导航:任何;> }) => React.ReactNode;

export declare type ScreenListeners<State extends NavigationState, EventMap extends EventMapBase> = Partial<{
    [EventName in keyof (EventMap & EventMapCore<State>)]: EventListenerCallback<EventMap, EventName>;
}>;
declare type ScreenComponentType<ParamList extends ParamListBase, RouteName extends keyof ParamList> = React.ComponentType<{
    route: RouteProp<ParamList, RouteName>;
    navigation: any;
}> | React.ComponentType<{}>;
export declare type RouteConfigComponent<ParamList extends ParamListBase, RouteName extends keyof ParamList> = {
    /**
     * React component to render for this screen.
     */
    component: ScreenComponentType<ParamList, RouteName>;
    getComponent?: never;
    children?: never;
} | {
    /**
     * Lazily get a React component to render for this screen.
     */
    getComponent: () => ScreenComponentType<ParamList, RouteName>;
    component?: never;
    children?: never;
} | {
    /**
     * Render callback to render content of this screen.
     */
    children: (props: {
        route: RouteProp<ParamList, RouteName>;
        navigation: any;›
    }) => React.ReactNode;
    component?: never;
    getComponent?: never;

0
投票

您可以使用参数来完成此操作。要设置初始参数或道具,您可以使用

initialParams
,如下所示:

<Tab.Screen
    name="Home"
    component={HomeScreen}
    options={{
        initialParams={
            name: 'Your name'
        }
    }}
/>

然后你可以使用 prop

route
访问参数,如下所示:

const HomeScreen = ({ route }) => (
    <View>
        <Text>Welcome to my app, {route.params.name}</Text>
    </View>
)

或使用

useRoute
钩子:

const HomeScreen = () => {
    const { params } = useRoute()
    return (
        <View>
            <Text>Welcome to my app, {params.name}</Text>
        </View>
    )
}

更新: 您还可以使用道具

navigation
通过调用
navigation.getParam()
来访问参数,如下所示:

const HomeScreen = ({ navigation }) => (
    <View>
        <Text>Welcome to my app, {navigation.getParam('name', 'Anonymous')}</Text>
    </View>
)

navigation.getParam()
采用两个参数,参数名称和默认值。您可以使用
useNavigation
钩子执行相同的操作。

当您从另一个屏幕导航时,您甚至可以通过将 传递给

navigation.navigate
的第二个参数来传递参数:

const LoginScreen = ({ navigation }) => {
    const [name, setName] = useState('')
    return (
        <View>
            <TextInput 
                placeholder="Type your name here"
                value={name}
                onChangeText={(text) => setName(text)}
            />
            <Button 
                title="Submit"
                onPress={() => navigation.navigate('Home', {
                    /* Pass your params here */
                    name
                })}
            />
        </View>
    )
}

您还可以使用

HomeScreen
更改
navigation.setParams
组件中的参数并传入新参数:

const HomeScreen = ({ route, navigation }) => (
    <View>
        <Text>Welcome to my app, {route.params.name}</Text>
        <Button 
            title="Reset name"
            onPress={() => navigation.setParams({
                name: ''
            })}
        />
    </View>
)

注意: 如果组件是导航器中使用的页面,则只能访问

route
navigation
属性。

有关传递参数的更多信息,请访问 https://reactnavigation.org/docs/params

虽然这是更流行的方法,但还有其他方法可以完成此任务,例如传递

children
Tab.Screen
属性作为内联组件,或者将屏幕数据置于应用程序状态。您可以选择要采用的方法,但 React 导航参数可能是您的最佳选择。

© www.soinside.com 2019 - 2024. All rights reserved.