Learner
Learner

Reputation: 33

Passing props and navigation in react navigation

I have a parent functional component Layout which needs props to have access to it's children. However, as I am using navigation 5.x, I also need to pass navigation but what I have tried hasn't worked yet. Here is my work

import { Container, Header, Content, Left, Right } from 'native-base';
import React from 'react';
import { View } from 'react-native';
import Icon from 'react-native-vector-icons/FontAwesome';
import { useNavigation } from '@react-navigation/native';

const Layout = (props, navigation) => {

        return (
            <Container >
                <Header style={{ alignItems: 'center', backgroundColor: '#3a455c', height: 50 }}>
                    <Left style={{ flexDirection: 'row' }}>
                        <MaterialIcon style={{ color: 'white', marginRight: 10 }} onPress={ () => console.log(navigation) } size={30} color="black" name= 'menu' />
                    </Left>
                    <Icon onPress={ () => navigation.navigate('Index') } size={20} style={{marginTop: 4, marginLeft: 130}} color="white" name= 'home' />
                    <Right style={{ flexDirection: 'row' }}>
                        <Icon onPress={ () => navigation.navigate('Index') } size={20} style={{marginTop: 4}} color="green" name= 'user' />
                    </Right>
                </Header>
                <Content >
                    <View>
                        { props.children }
                    </View>
                </Content>
            </Container>
        );
}

export default Layout;

Layout component is being rendered in Newsletter component

function Newsletter() {

        const navigation = useNavigation();
        return (
            <Layout >
                <ScrollView style={{ marginTop: 40, marginLeft: 12 }}>
                    <Text style={{fontSize: 24, fontFamily: 'sans-serif-medium', textAlign: 'center', fontWeight: 'bold'}} > Directed Distraction </Text>
                    <View>
                        <Text style={{ marginTop: 12, fontSize: 18, textAlign: 'left', fontStyle: 'italic' }}>
                        Elon Reeve Musk FRS (/ˈiːlɒn/; born June 28, 1971) is an engineer,
                         industrial designer, technology entrepreneur and philanthropist.
                          He is a citizen of South Africa, Canada, and the United States.
                          He is based in the United States, where he immigrated to at age 20 and 
                         has resided since. He is the founder, CEO and chief engineer/designer 
                         of SpaceX; early investor, CEO and product architect of Tesla, 
                         Inc.; founder of The Boring Company; co-founder of Neuralink; and 
                         co-founder and initial co-chairman of OpenAI. He was elected a Fellow of 
                         the Royal Society (FRS) in 2018. In December 2016, he was ranked 21st 
                         on the Forbes list of The World's Most Powerful People, and was ranked 
                         joint-first on the Forbes list of the Most Innovative Leaders of 2019. 
                         A self-made billionaire, as of July 2020 his net worth was estimated at $44.9
                          billion and he is listed by Forbes as the 22nd-richest person in the world.
                           He is the longest tenured CEO of any automotive manufacturer globally.
                        </Text>
                        <Button title="a" onPress={ () => console.log(navigation) }></Button>
                    </View>
                </ScrollView>
            </Layout>
    );
}

navigation is printed just as an object{}. Help would be appreciated.

Upvotes: 1

Views: 772

Answers (1)

Eslam Adel
Eslam Adel

Reputation: 1189

I will explain something first: the navigation object gets passed to the prop object when this component rendered as a screen for any navigator and not next to it so you can do a couple of things now

1- const Layout = (props) and you can access the navigation like how you access the children like this props.navigation.navigate('Index')

2- or you can simply destructure anything you want from the props object like this: const Layout = ({children, navigation}) => { this way you can type less as you don't have to reference the props object anymore and it will be navigation.navigate('Index')

3- if your component does not rendered by a navigator, then the navigation object will not be passed to the prop object and it will be undefined -- in this case there is a simple solution you can do and it's not the only solution:

I see that you already importing useNavigation and useNavigation exposes the navigation object out of the box for you, so what you can do inside your component is: const navigation = useNavigation() then you can use navigation as always, but don't forget to remove the navigation from the component parameters here you can find more details about the useNavigation hook useNavigation

4- here I will add the code for the layout component which I believe it should work

import { Container, Header, Content, Left, Right } from 'native-base';
import React from 'react';
import { View } from 'react-native';
import Icon from 'react-native-vector-icons/FontAwesome';
import { useNavigation } from '@react-navigation/native';

const Layout = (props) => {
const navigation = useNavigation();
        return (
            <Container >
                <Header style={{ alignItems: 'center', backgroundColor: '#3a455c', height: 50 }}>
                    <Left style={{ flexDirection: 'row' }}>
                        <MaterialIcon style={{ color: 'white', marginRight: 10 }} onPress={ () => console.log(navigation) } size={30} color="black" name= 'menu' />
                    </Left>
                    <Icon onPress={ () => navigation.navigate('Index') } size={20} style={{marginTop: 4, marginLeft: 130}} color="white" name= 'home' />
                    <Right style={{ flexDirection: 'row' }}>
                        <Icon onPress={ () => navigation.navigate('Index') } size={20} style={{marginTop: 4}} color="green" name= 'user' />
                    </Right>
                </Header>
                <Content >
                    <View>
                        { props.children }
                    </View>
                </Content>
            </Container>
        );
}

export default Layout;

there other options like passing a handler to onPress and executing this function from the component where has access to the navigation object

I hope this is useful to you. let me know if it works

Upvotes: 2

Related Questions