React native TabNavigator navigation params - react-native

I want to send route params to Profile tab from button click action in Home screen. Below code is tab navigator
const Tabs = TabNavigator({
[routes.HOME]: {
screen: FeedMainScreen,
navigationOptions: {
tabBarLabel: tabBarLabels.HOME_TAB_LABEL,
},
},
[routes.SEARCH]: {
screen: SearchScreen,
navigationOptions: {
tabBarLabel: tabBarLabels.SEARCH_TAB_LABEL,
},
},
[routes.PROFILE]: {
screen: ProfileScreen,
navigationOptions: {
tabBarLabel: tabBarLabels.PROFILE_TAB_LABEL,
},
},
}
and button click navigation is like this
<Button onPress={() => this.props.navigation.navigate(routes.PROFILE, { id: this.props.user._id }, null)} />
and accsess param from Profile screen like this
constructor (props) {
super(props)
console.log('NavPrams', this.props.navigation.state)
}
alwaya undifined

You can use connect() method to successfully map the props and use them anywhere.
Add the below mentioned code in the class where is written -
const mapStateToProps = state => {
return {
user: this.props.user;
};
};
export default connect(mapStateToProps, {})(className);

Related

Call child react navigation prop from super component in react-native / react-navigation

I have a react native application using react navigation. I have following structure in my application.
class MainContainer extends Component {
render() {
return (
<View style={{ flex: 1 }}>
<Header
backgroundColor={appcolors.primaryColor}
leftComponent={<TouchableOpacity onPress={() => this.props.navigation.toggleDrawer() }><Feather name='align-justify' size={24} color='white' /></TouchableOpacity>}
centerComponent={{ text: this.props.headerTitle , style: { color: 'white' } }}
/>
<MainDrawerNavigation/>
</View>
);
}
};
and <MainDrawerNavigation/> is a react navigation component as follows.
MainDrawerNavigation = createDrawerNavigator({
XScreen: {
screen: XScreen,
},
YScreen: {
screen: YScreen,
},
ZScreen: {
screen: ZScreen,
},
},{
}
});
I have got error when trying to call this.props.navigation.toggleDrawer() from MainContainer. Then for testing purpose I have add a button to XScreen and tried to toggle drawer and it was success. So I want to know is there any way to pass child navigation props to super view. So I could call this.props.navigation.toggleDrawer() method and control drawer from MainContainer. or any navigation practices that can be use to solve this.
PS: the error I got is _this2.props.navigation.toggleDrawer is not a function
In MainContainer, the this.props.navigation is not initiated, so you got such error. You can only access it inside the child component of MainDrawerNavigation i.e. XScreen, YScreen & ZScreen only.
For best practices you need to design how all component will navigate into your app and pass Navigator objects/components as root component.
There are multiple navigators, you will can read them react navigation api doc.
A simplified app needs SwitchNavigator, DrawerNavigator, TabBarNavigator & StackNavigator.
SwitchNavigator :
It is used for user authentication. It will give control to toggle between two component (FYI, component can be a Navigator or React.Component).
export const AuthNavigator = SwitchNavigator(
{
AuthLoading: { screen: AuthLoadingScreen },
App: { screen: AppDrawer},
Auth: { screen: AuthStack}
},
{
initialRouteName: 'AuthLoading',
}
);
for more details
DrawerNavigator :
It is used to display side panel or sliding view at left or right side of the screen. So, you can directly pass this component to SwitchNavigator's authentication successful screen.
export default const AppDrawer = DrawerNavigator(
{
Home: { screen: TabBarNav },
Notes: { screen: NotesStack },
Invite: { screen: InviteContactsStack },
Files: { screen: FilesStack },
Settings: { screen: SettingsStack }
},
{
initialRouteName: "Home",
contentOptions: {
activeTintColor: "#e91e63"
},
contentComponent: props => <LeftSidePanel {...props} />
}
);
TabBarNavigator :
It is used to display tab bar at bottom for iOS and at top for android by default. This can be customized.
export default const TabBarNav = TabNavigator(
{
ChatsTab: {
screen: ChatsStack,
navigationOptions: {
tabBarLabel: "Chats"
}
},
InviteContacts: {
screen: InviteContactsStack,
navigationOptions: {
tabBarLabel: "Invite"
}
},
Notifications: {
screen: NotificationsStack,
navigationOptions: {
tabBarLabel: "Notifications"
}
},
Tasks: {
screen: TasksStack,
navigationOptions: {
tabBarLabel: "Tasks"
}
}
},
{
tabBarPosition: "bottom",
}
);
StackNavigator :
It's name suggests that it will hold a stack of component. So, when any item is selected from drawer, you can directly put a StackNavigator in that screen.
export default const ChatsStack = StackNavigator({
Chats: {
screen: Chats
},
Messages: {
screen: Messages
}
});
You can read Spencer Carli's blog on medium which explain with code.
Please let me know whether it satisfies your need.

React navigation mix navigation

Im using react-navigation to build my app, I want to have both tab and stack navigation so I did this:
const FindPage = StackNavigator({
Find: {
screen: Find,
},
Item:{
screen:Item
}
}, {
initialRouteName: 'Find',
});
const ProfilePage = StackNavigator({
Profile: {
screen: Profile,
},
Item:{
screen:Item
}
}, {
initialRouteName: 'Profile',
});
const MyApp = createBottomTabNavigator({
Find: FindPage,
Profile: ProfilePage
}
});
const auth = StackNavigator({
Login:{
screen: Login,
},
Register:{
screen: Register,
},
Main:{
screen: MyApp,
}
},{
initialRouteName: 'Main',
headerMode: 'none'
});
export default auth;
But I dont get it well. this is what the screenshot is
giving:
enter image description here
if you see the tab lost it tab icon and font when im using stacknavigation in tab navigation, this worked for me in another version of react nvigation and cant find anything on the web Please Help !
with reactnavigation2 you can achieve this like in the below code
Read more about it here https://reactnavigation.org/docs/en/bottom-tab-navigator.html
import Ionicions from "react-native-vector-icons/Ionicons";
screen: createBottomTabNavigator(
{
HomeScreen: {
screen: HomeStack,
navigationOptions: {
tabBarLabel: props => <Label name="Home" {...props} />,
tabBarIcon: props => (
<Icon name="ios-home-outline" fillname="ios-home" {...props} />
)
}
}
})

Custom header in nested TabNavigator

I have a fairly complication navigation flow requirement for an app I'm working on.
I have a bottom tab bar, for each tab I'll be having a top tab bar for additional related views.
Which I have working, however on the videos tab in the nested "All" tab, I need to add a search bar to the header, and on the "Favourites" tab I'll be having yet another custom header with an "Edit" button at the top right.
How can I achieve this navigation whilst allowing React Navigation to co-ordinate everything. See images below:
What I don't want to do is disable the header at the MainNavigator level and enable it for particular routes. Or even worse embed the header and the tab bar on individual containers.
routes.js
import {
StackNavigator,
TabNavigator,
DrawerNavigator
} from "react-navigation";
import Feed from "./containers/Feed";
import Auth from "./containers/Auth";
import News from "./containers/News";
import Videos from "./containers/Videos";
import FavouriteVideos from "./containers/FavouriteVideos";
const DashboardNavigator = TabNavigator(
{
Feed: {
screen: Feed
},
News: {
screen: News
}
},
{
tabBarPosition: "top"
}
);
const VideoNavigator = TabNavigator(
{
Videos: {
screen: Videos,
navigationOptions: {
title: "All"
}
},
Favourites: {
screen: FavouriteVideos
}
},
{
tabBarPosition: "top"
}
);
const MainNavigator = TabNavigator(
{
Dashboard: {
screen: DashboardNavigator,
navigationOptions: ({}) => ({
title: "Dashboard"
})
},
Video: {
screen: VideoNavigator,
navigationOptions: ({}) => ({
title: "Videos"
})
}
},
{
swipeEnabled: false,
animationEnabled: false,
tabBarPosition: "bottom"
}
);
const AuthenticatedNavigator = DrawerNavigator({
App: {
screen: MainNavigator
}
});
const RootNavigator = StackNavigator({
LoggedOut: {
screen: Auth
},
Authenticated: {
screen: AuthenticatedNavigator
}
});
export default RootNavigator;
Snack
https://snack.expo.io/H1qeJrLiM
Images
You can use react-navigation addListener function with combination setParams to achieve desired behavior.
You can listen for focus and blur events and then change a parameter. Then in your route config you can look for this parameter and decide what to render for header. I changed your snack to show a working example of what I am suggesting.
Example
const MainNavigator = TabNavigator(
{
Dashboard: {
screen: DashboardNavigator,
navigationOptions: ({}) => ({
title: "Dashboard"
})
},
Video: {
screen: VideoNavigator,
navigationOptions: ({navigation}) => {
let title = 'Videos';
navigation.state.routes.forEach((route) => {
if(route.routeName === 'Videos' && route.params) {
title = route.params.title;
}
});
// I set title here but you can set a custom Header component
return {
tabBarLabel: 'Video',
title
}
}
}
},
{
swipeEnabled: false,
animationEnabled: false,
tabBarPosition: "bottom"
}
);
export default class Videos extends Component {
constructor(props) {
super(props);
this.willFocusSubscription = props.navigation.addListener(
'willFocus',
payload => {
this.props.navigation.setParams({title: 'All Videos'});
}
);
this.willBlurSubscription = props.navigation.addListener(
'willBlur',
payload => {
this.props.navigation.setParams({title: 'Just Videos'});
}
);
}
componentWillUnmount() {
this.willFocusSubscription.remove();
this.willBlurSubscription.remove();
}
render() {
return (
<View>
<Text> Videos </Text>
</View>
);
}
}

How to back from Facebook in drawerNavigator [react-native]

i created drawer navigator and one of option is open facebook page (from app or URL) it's work fine but after the openning facebook page i try to go back and its threwing error..
i try try to fix that with return null after 'catch' and the error disappeare but its return to null page and i need to click back again to actually return to the right page.
what can i do to fix that?
class Root extends Component {
render(){
const { navigation } = this.props.navigation;
const Drawer = DrawerNavigator({
Home:{
screen: HomeScreen,
navigationOptions: {
drawerLabel: 'home',
},
},
FacebookPage: {
screen: () => { Linking.canOpenURL('fb://page/1000000000')
.then((supported) => {
if (!supported) {
Linking.openURL('http://facebook.com/1000000000/')
} else {
Linking.openURL('fb://page/1000000000')
}})
.catch(err => Alert.alert(err))
},
navigationOptions: {
drawerLabel: 'Facebook',
},
},
MyAccount:{
screen: MyAccountScreen,
navigationOptions: {
drawerLabel: "My account",
},
},
},
{
initialRouteName: 'Home',
});
return(
<Drawer/>
)}
}
export default Root;

How to handle click event on tab item of TabNavigator in React Native App using react-navigation?

I am programming React Native App. I am using react-navigation for navigating screens.
I have 2 Stack Navigators, they are stayed in a Tab Navigator. I want handle click event when I press tab item on TabBar to refresh its view.
export const HomeStack = StackNavigator({
Home: {screen: ScreenHome},
Detail: {screen: ScreenDetail}
})
export const UserStack = StackNavigator({
User: {screen: ScreenUser}
})
export const Tabbar = TabNavigator({
HomeTab: {
screen: HomeStack,
},
UserTab: {
screen: UserStack,
}
}, {
tabBarComponent: ({ jumpToIndex, ...props}) => (
<TabBarBottom
{...props}
jumpToIndex={(index) => {
if(props.navigation.state.index === index) {
props.navigation.clickButton(); //----> pass props params (code processes)
}
else {
jumpToIndex(index);
}
}
}
/>
),
tabBarPosition: 'bottom'
});
class TabClass extends Component{
constructor(props){
super(props)
this.clickButton = this.clickButton.bind(this)
}
clickButton(){
console.log('click button')
}
render (){
return (
<Tabbar clickButton={()=> this.clickButton()}/>
)
}
}
I want to pass clickButton() function from TabClass Component to the code which processes event click tab bar. When if(props.navigation.state.index === index), I want it will call clickButton(). I try it but it doesn't work.
Is there any way to solve my matter?
I tried onNavigationStateChange(prevState, currentState).
class TabClass extends Component{
constructor(props){
super(props)
this.clickButton = this.clickButton.bind(this)
}
clickButton(){
console.log('click button')
}
_handleNavagationStateChange(prevState, currentState){
console.log('handle navigation state change')
}
render (){
return (
<Tabbar onNavigationStateChange={(prevState, currentState) => {
this._handleNavagationStateChange(prevState, currentState)
}}
clickButton={()=> this.clickButton()}
/>
)
}
}
However, _handleNavagationStateChange(prevState, currentState) only run when navigation state changes (for examples, if I stay at HomeTab, I click User Tab Item, this function will run; if I stay at HomeTab, I click Home Tab Item, this function will not run).
Is there any way to handle click event on tab item.
according to the newest documentation here, you can use navigationOptions: {navigationOptions: () => doWhatever()} to handle tab bar taps.
From the react-navigation 4.x docs, you can override tabBarOnPress within navigationOptions:
tabBarOnPress: ({ navigation, defaultHandler }) => {
defaultHandler(); // Call the default handler to actually switch tabs
// do extra stuff here
},
Please try the code following when customize the event touch of TabBar:
import { TabBarBottom, TabNavigator, StackNavigator } from 'react-navigation';
export const MainScreenNavigator = TabNavigator({
Home: { screen: HomeViewContainer },
Search: { screen: SearchViewContainer },
}, {
tabBarComponent: ({ jumpToIndex, ...props, navigation }) => (
<TabBarBottom
{...props}
jumpToIndex = { tabIndex => {
const currentIndex = navigation.state.index;
if (tabIndex == 1) {
// do some thing. Call Native Live Stream Record
} else {
jumpToIndex(tabIndex);
}
console.log('Select tab: ', tabIndex);
}}
/>),
tabBarPosition: 'bottom',
});