React Navigation Custom Header and Custom Back Button - react-native

I am using React Navigation. I created a custom header component myself. I call this component into other components. But the back button I use on the header doesn't work for other components. How can I add this to the react navigation stack.
navigation.back() or navigation.navigate('Home)
I get an error when I write.

Maybe you not transmit navigation? print console.log(navigation). And you can use navigation.goBack()

You can use this: function LeftMenu(props) { return ( <Drawer.Navigator initialRouteName={props.route} drawerContent={(props) => <Custom_Side_Menu {...props}/>} drawerContentOptions={{activeTintColor: 'rgb(219,218, 218)'}}> <Drawer.Screen name="Map" component={MapScreen}/> </Drawer.Navigator> ); }
And you can get navigation in props LeftMenu

Related

How can I navigate from login screen to a bottomtab screen?

How can I navigate to a bottomtab screen rather than a stack screen? The goal is to take the user to the main home page onPress of the sign in button. I initially created a Stack.Screen and added the homescreen component but that crashed the header and the bottom tab navigation and there was also the back button in the header which isn't supposed to be because the home screen is the main screen. Is there a way to navigate to the bottom tab screen from the sign in component? I'm a beginner by the way and also not so good at using stack overflow
if you're using react router than this may possible with useNavigate() and Link. Also you can add custom javascript window.location.href ="/pagename"
Usage of useNavigate() before return of function-
const navigate = useNavigate()
onClick = (e)=>(
e.preventDefault()
navigate('/home')
)
Usage of Link inside body-
<Link to="/home"></Link>
Usage of custom javascript inside body-
<button onClick = (()=>window.location.href="/home"))>Click me</button>
Hope you'll like the answer. But if you still face any issue just lemme know.
I suggest you to try an Authentication flow approch written by 'React-Navigator' API.
The main idea of that is using 2 Navigators.
Stack Navigator for 'Login'
Tab Navigator for pages which logged in users can see
However, to make this flow available, you need to add Global State Management library like Redux / React Context to handle which navigator is showing. Once the state is set, the app will auto select the navigator used. You don't need to call any function for navigation.
<NavigationContainer>
<Stack.Navigator>
{
!redux.isLoggedIn ?
<Stack.Group>
<Stack.Screen
name="auth"
component={Auth}
/>
</Stack.Group>
:
<Stack.Group>
<Stack.Screen
name="home"
component={YourHomeTabNavigator}
/>
</Stack.Group>
}
</Stack.Navigator>
</NavigationContainer>

Why useNavigation hook doesn't work in custom side bar?

If I create custom drawer:
<DrawerStack.Navigator
drawerContent={props => <SideMenu {...props} />}>
It requires to pass props in order to get navigation object inside it.
And if I have following:
<ClientsStack.Navigator>
<ClientsStack.Screen name="Clients" component={ClientsScreen} />
<ClientsStack.Screen
name="ClientDetails"
component={ClientDetailsScreen}
/>
</ClientsStack.Navigator>
And inside ClientsScreen I have FlatList which has:
renderItem={({ item }) => <ClientCard id={item.id} />}
inside ClientCard component which is not screen it's just dummy component
I can use useNavigation hook there.
Why it can be used there but not in custom drawer component?
You can't use useNavigation inside your drawerContent cause the hook is only available from your screens and their childs.
At the origin the only way to get navigation was to pass it from your screen to their childs. But since the useContext hook exist, the library provides a useNavigation to easily get the navigation in deep nested components. (and simplify the code a lot)
A drawer custom component is not a screen or wrapped into a screen. So there is just no reason to get the navigation from it with useNavigation. And I easily guess there is no usecase where we have deep nested components inside it cause it is usually just a menu.

In React Native app passing navigation to class component puts it in another navigation object

In my React Native app, when I pass navigation to a class component, it puts it in another navigation object and now I have to add one more navigation to call the navigate() method.
So, instead of this.props.navigation.navigate("somewhere"),
I have to use this.props.navigation.navigation.navigate("somewhere")
Here's how I pass navigation from a functional to a class component:
const ParentComponent = ({ navigation }) => {
return(
<View>
<ChildComponent navigation={navigation} />
</View>
);
}
export default ParentComponent;
And in the child component which happens to be a class component with access to Redux store, I recieve navigation like this:
class ChildComponent extends Component {
render() {
return(
<View>
<TouchableOpacity onPress={() => this.props.navigation.navigation.navigate("Route123")}>
<Text>Go to Route 123</Text>
</TouchableOpacity>
</View>
);
}
}
function mapStateToProps(state, navigation) {
myAccount: state.account.myAccount,
navigation: navigation
}
export default connect(mapStateToProps)(ChildComponent);
Notice that in the ChildComponent, I had to add one more navigation to access the navigate function i.e. this.props.navigation.navigation.navigate("Route123");
I think I'm making a fairly fundamental mistake somewhere but not sure where.
The version of React Navigation in my app is as follows and the React Native version is 0.66.3:
"#react-navigation/drawer": "^6.1.8",
"#react-navigation/material-bottom-tabs": "^6.0.9",
"#react-navigation/native": "^6.0.6",
"#react-navigation/native-stack": "^6.2.5",
As #Hagai Harari stated, you should not put navigation as the second parameter of mapStateToProps function. As described here, second parameter of mapStateProps takes ownProps which corresponds to the component props.
You can use withNavigation. But when I see your dependencies, you are using react-navigation#^6 which does not have HOC called as withNavigation.
You can choose to use this.props.navigation after removing unnecessary navigation param from mapStateToProps.
What I would suggest is to use functional component instead of class components, then you will be able to use useNavigation which react-navigation#^6 exposes. In the end, you will obtain navigation object without repetition of passing it down to children components.

React Navigation passing function as parameter

so i have lot of screen that have similar function eg:
ForgotPasswordCaptcha
ForgotUserIDCaptcha
RegisterCaptcha
these screens have same layout and functionality except they have different "Next" Button function in ForgotPassword users will be redirected into loginscreen, in ForgotUserID the user will be redirected into page that shows his userID. and in Register it will redirect user to Succes Page.
.
so the function that i create in navigator is handleOkay, and when i press the button in SomeReusableScreen it gives me this warning
Non-serializable values were found in the navigation state. Check:
forgotUserIDStackScreen > FUinputCASAScreen > params.handleOkay (Function)
This can break usage such as persisting and restoring state. This might happen if you passed non-serializable values such as function, class instances etc. in params.
what i want to achieve is i to pass function as parameter in Stack navigator so the screen will just invoke that function to redirect/doing something with redux,
i dont know i should ignore this warning since in other screens it will handle redux sagas, set asyncstorage
so i have found the way to do what i wanted.
instead of passing the screen as component in Stack.Screen i pass it as child like this
<Stack.Screen
initialParams={{progress: 0.2}}
name={routes.nameofthisroute}
options={({navigation, route}) => ({
headerTitle: props => {
let currentProps = {navigation, route};
return <NavigationHeaderTwo {...currentProps} />;
},
...otherStyle,
})}>
{props => (
<PickMethodScreen handlePickMethod={handlePickMethod} {...props} />
)}
</Stack.Screen>
and i props some function and state from Stack Navigator and its written in this docs here
we can also create react context so component can consume it without having lot of props
I implemented a very simple example to clear the concept. You can pass function as a prop and can dispatch up to the parent component using the same props key. This way you can utilize reusable component.
//consider this your generic Component
function IButton(props){
//receive the method as props
//dispatch the method back to the parent
return (
<button onClick={()=>props.handleClick('hello')}>click me </button>
)
}
const App=()=>{
function handleOnClick(text){
alert(text);
}
return(
<div>
{/*pass the function as Prop*/}
<IButton handleClick={handleOnClick}/>
</div>
)
}
ReactDOM.render( < App / > , document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>

Initial route params in React Navigation v5?

React Navigation v3 was featuring an initialRouteParams property to pass initial values to this.navigation.props. Is there a way to set initial route params to be accessed via route.params in the React Navigation v5?
function MainScreen({route, navigation}) {
return (
// how to pass default values to route in here?
// route.params.userParam ?
...
);
}
It could be accomplished by passing initialParams to the Stack.Screen:
<Stack.Screen
name="Main"
component={MainScreen}
initialParams={{ /* initialParams */ }}
/>
There is also a handy default syntax one can use (see No more getParam):
route.params?.userParam ?? 'defaultValue'