react-native, how to factorize code over many tabs - reactjs

I use react-native to create ios and android app
I create a test app with TabNavigator working good plus a sidemenu ( the button to open it should be in the top action bar ) and floatings actions buttons (the red circle labeled FAB on the picture). All this code is new defined on first tab : app.js.
Each tab have it's own js file with code and render.
My question is :
How to get this sidemenu,action bar and floating buttons on ALL tabs without coping all the render code and js functions over all the other tabs Js files.
when i click on a tab only the green part will change
my App.js
import React, { Component } from "react";
import {...} from "react-native";
import { TabNavigator } from "react-navigation";
import Imagetest from "./Photo";
import ListFlatlist from "./ListFlatlist";
... // importing the other file for the tabs
import styles from "./css/styles";
import SideMenu from "react-native-side-menu";
import Menu from "./Menu";
class App extends Component {
constructor(props) { ... }
...
render() {
const menu = <Menu onItemSelected={this.onMenuItemSelected} />;
return (
<SideMenu
menu={menu}
isOpen={this.state.isOpen}
onChange={isOpen => this.updateMenuState(isOpen)}
>
<View style={styles.container}>
{/* my app.js content
*/}
// this is floating buttons
<ActionButton buttonColor="rgba(231,76,60,1)">
<ActionButton.Item buttonColor='#9b59b6' title="New Task" onPress={() => console.log("notes tapped!")}>
<Icon name="md-create" style={styles.actionButtonIcon} />
</ActionButton.Item>
</ActionButton>
</View>
</SideMenu>
);
}
}
const AppNavigator = TabNavigator(
{
H: { screen: App },
f: { screen: ListFlatlist },
Img: { screen: Imagetest },
B: { screen: Buttonpage },
S: { screen: ListSectionlist },
F: { screen: Fetchpage }
}
);
export default AppNavigator;
If a create new components for sidemenu, action bar and FAB I have to put them on all the tab render, not the cleanest way for me but i don't see other solution now.

I put an example repo together on Github. Thats actually all it needs:
// #flow
import React, { Component } from "react";
import { View } from "react-native";
import { StackNavigator, TabNavigator } from "react-navigation";
import ActionButton from "react-native-action-button";
import Profile from "./Profile";
import Tab1View from "./Tab1";
import Tab2View from "./Tab2";
import Tab3View from "./Tab3";
const TabView = TabNavigator({
tab1: { screen: Tab1View },
tab2: { screen: Tab2View },
tab3: { screen: Tab3View },
})
const Home = (props) => {
return (
<View style={{flex: 1}}>
<TabView navigation={props.navigation} />
<ActionButton offsetY={100} />
</View>
);
}
Home.router = TabView.router;
const StackView = StackNavigator({
home: { screen: Home },
profile: { screen: Profile },
});
export default class App extends Component {
render() {
return (
<View style={{ flex: 1 }}>
<StackView />
</View>
);
}
}

Related

How to navigate other screen by declaring another class inside of the first class using react navigation

I'm currently new here on this react native, I got confuse regarding switching my screen to another screen, I don't know why my import second screen not working when i click the onpress function declared to my first screen.,
import SecondScreen from './Screens/SecondScreen';
export default class FirstScreen extends Component<Props> {
render() {
return (
<View style={styles.container}>
<Header searchBar rounded>
<Left>
<Button transparent>
<Icon name='menu'/>
</Button>
</Left>
<Body>
<Title>Pay Bills</Title>
</Body>
<Item>
<Icon name="ios-search" />
<Input placeholder="Search" />
<Icon name="ios-people" />
</Item>
<Button transparent>
<Text>Search</Text>
</Button>
</Header>
<StatusBar backgroundColor='#6633ff' barStyle='light-content' />
<Text>How much would you like to pay?</Text>
<View style={{flex:1}}>
<Image onPress={()=> this.props.navigation.navigate('SecondScreen')} source={require('./Assets/example.png')}
style={{flex:1,width:null,height:null,resizeMode:'cover'}}
/>
</View>
</View>
);
}
}
As you can see I use the onpress function to navigate second screen.
onPress={()=> this.props.navigation.navigate('SecondScreen')}
My app.js file
/**
* Sample React Native App
* https://github.com/facebook/react-native
*
* #format
* #flow
*/
import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View, SafeAreaView, ScrollView, Dimensions} from 'react-native';
import {createDrawerNavigator, DrawerItems} from 'react-navigation';
//screens
import LoginScreen from './Screens/LoginScreen';
const instructions = Platform.select({
ios: 'Press Cmd+R to reload,\n' + 'Cmd+D or shake for dev menu',
android:
'Double tap R on your keyboard to reload,\n' +
'Shake or press menu button for dev menu',
});
type Props = {};
export default class App extends Component<Props> {
render() {
return (
<AppDrawerNavigator/>
);
}
}
const AppDrawerNavigator = createDrawerNavigator({
Login:LoginScreen,
});
How to move my first screen to the second screen using react navigation.
thanks.
pass the route of second screen also in react navigation
then you can navigate to second screen
You need to make some change in app.js. add createDrawerNavigator inside createStackNavigator. Add those screen into stacknavigator in which you do not want to add into drawer. In createDrawerNavigator add those screens in which you want to show in drawer.
Please check following code
import React, { Component } from "react";
import {
Platform,
StyleSheet,
Text,
View,
SafeAreaView,
ScrollView,
Dimensions
} from "react-native";
import { createStackNavigator,createDrawerNavigator DrawerItems } from "react-navigation";
//screens
import LoginScreen from "./Screens/LoginScreen";
const instructions = Platform.select({
ios: "Press Cmd+R to reload,\n" + "Cmd+D or shake for dev menu",
android:
"Double tap R on your keyboard to reload,\n" +
"Shake or press menu button for dev menu"
});
type Props = {};
export default class App extends Component<Props> {
render() {
return( <StackNav />);
}
}
const StackNav = createStackNavigator(
{
Drawer: {
screen:AppDrawerNavigator ,
navigationOptions: {
headerMode: "none",
header: null
}
},
First: {
screen: First,
navigationOptions: {
headerMode: "none",
header: null
}
},
Second: {
screen: Second,
navigationOptions: {
headerMode: "none",
header: null
}
}
},
{
initialRouteName: "Drawer"
}
);
const AppDrawerNavigator = createDrawerNavigator({
Login: { screen: LoginScreen },
})

Navigation('DrawerOpen') is not working

I am making an app following this tutorial:
I just did it exacly the same. It compiles but the button of the Drawer Menu does not work. This is the code where the button is:
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import {createBottomTabNavigator} from 'react-navigation';
import ScreenOne from './TabNavigator/ScreenOne';
import ScreenTwo from './TabNavigator/ScreenTwo';
import { Container, Header,Left,Right,Icon } from 'native-base';
export default class AppTabNavigator extends React.Component{
static navigationOptions = ({navigation}) =>{
return{
headerLeft:(
<View style={{padding:10}}>
<Icon name ="menu" style={{fontSize: 24, color : 'black'}} onPress={()=>navigation.navigate('DrawerOpen')} />
</View>
)
}
}
render(){
return(
<HomeScreenTabNavigator screenProps={{navigation: this.props.navigation}}/>
)
}
}
const HomeScreenTabNavigator = new createBottomTabNavigator({
ScreenOne:{
screen: ScreenOne,
navigationOptions:{
tabBarLabel: 'Feed'
}
},
ScreenTwo:{
screen: ScreenTwo,
navigationOptions:{
tabBarLabel: 'Feed' }
}
})
Since version 2.X of react-navigation you can't use the following code:
navigation.navigate('DrawerOpen')
But instead you need to use:
navigation.openDrawer()
See also the Drawer documentation

Using Routing in react-native

I have button as mentioned below and I have an another page named JobDetails on the same folder in the project. When I click on the button "next" i need to display that JobDetails page. I have added onButtonPress with alert function and it works fine. I'm not sure on how to bring the next page on clicking the button using routing.
onButtonPress(){
alert("Prem")
}
<TouchableOpacity onPress={this.onButtonPress.bind(this)} style={styles.buttonStyle} >
<Text style={styles.nextPage}>
Next
</Text>
</TouchableOpacity>
It's very simple for react-native-router-flux, just do:
import { Actions } from 'react-native-router-flux';
onButtonPress(){
Actions.JobDetails();
}
Make sure your Scene key is correct (JobDetails in your case).
<Scene key="JobDetails" component={JobDetails} />
You can achieve this using Stack Navigator from react-navigation
Installation:
npm install --save react-navigation
Example:
import React from 'react';
import { View, Text, TouchableOpacity } from 'react-native';
import { StackNavigator } from 'react-navigation';
class MyHomeScreen extends React.Component {
static navigationOptions = {
title: 'Home'
}
onButtonPress(){
this.props.navigation.navigate('JobDetails'); // navigate to JobDetails screen!
}
render() {
return (
<TouchableOpacity onPress={this.onButtonPress.bind(this)} style={styles.buttonStyle} >
<Text style={styles.nextPage}>
Next
</Text>
</TouchableOpacity>
);
}
}
class JobDetailsScreen extends React.Component {
static navigationOptions = {
title: 'Job Details'
}
render() {
return (
<View>
<Text>I'm job screen!</Text>
</View>
);
}
}
const ModalStack = StackNavigator({
Home: {
screen: MyHomeScreen
},
JobDetails: {
screen: JobDetailsScreen
}
});
export default ModalStack;

Unable to Navigate to new screen from within FlatList

My first page with FlatList is :
import React, { Component } from 'react';
import { View, StyleSheet, FlatList, Text, TouchableHighlight } from 'react-native';
import { StackNavigator } from 'react-navigation';
import MoreInfo from './MoreInfo';
export default class Page1 extends Component {
constructor(props){
super(props);
}
render() {
const { navigate } = this.props.navigation;
return (
<View style={styles.container}>
<FlatList
data={users}
renderItem={
({item}) =>
<TouchableHighlight onPress={() => navigate('MoreInfo', { name: 'Jane' })}>
<Text style={styles.welcome}> {item.name} </Text>
</TouchableHighlight>
}
keyExtractor={item => item.index}
>
</FlatList>
</View>
);
}
}
const App = StackNavigator({
Page1: {screen: Page1},
MoreInfo: { screen: MoreInfo },
})
I am able to get the data displayed in a FlatList without using the navigation. But when I put Navigation and click any item on the list, I get the error:
Please help. Trying this since 3 days.
My index.android.js is
import React, { Component } from 'react';
import { AppRegistry} from 'react-native';
import MyApp2 from './src/components/MyApp2';
const MyApp2 = StackNavigator({
Page1: {screen: Page1},
MoreInfo: { screen: MoreInfo },
})
AppRegistry.registerComponent('MyApp2', () => MyApp2);
And My './src/components/MyApp2' is:
import React, { Component } from 'react';
import { StyleSheet, Text, View, TextInput, ScrollView, Alert,
FlatList, ActivityIndicator, Image,TouchableOpacity } from 'react-native';
import { Container } from 'native-base';
import AppHeader from './AppHeader';
import AppBody from './AppBody';
import AppFooter from './AppFooter';
export default class MyApp2 extends Component{
render(){
return(
<Container>
<AppHeader />
<AppBody/>
<AppFooter />
</Container>
)
}
}
I further have some tabs in the AppBody and including Page1 somewhere there. How would I go about it?
It doesn't look like you're importing Page1 anywhere and it's odd that you're importing MyApp2 and then defining a const for the StackNavigator that is also called MyApp2. I cannot test this since there are other files being imported, but I believe you just need to:
fix your imports,
fix your naming conflicts,
register all of your screens with StackNavigator so they all have access to the navigation prop,
and register the StackNavigator for your AppRegistry.
Try this:
Leave ./src/components/MyApp2 as is. Then make these edits (I'll be making the assumption that MyApp2, Page1, and MoreInfo are all located in ./src/components/:
Page1 file (whatever that is named):
import React, { Component } from 'react';
import { View, StyleSheet, FlatList, Text, TouchableHighlight } from 'react-native';
export default class Page1 extends Component {
constructor(props){
super(props);
}
render() {
const { navigate } = this.props.navigation;
return (
<View style={styles.container}>
<FlatList
data={users}
renderItem={
({item}) =>
<TouchableHighlight onPress={() => navigate('MoreInfo', { name: 'Jane' })}>
<Text style={styles.welcome}> {item.name} </Text>
</TouchableHighlight>
}
keyExtractor={item => item.index}
>
</FlatList>
</View>
);
}
}
index.android.js
import React, { Component } from 'react';
import { AppRegistry} from 'react-native';
import { StackNavigator } from 'react-navigation';
// Making an assumption for where these files are located
// since it's not in the original question.
import MyApp2 from './src/components/MyApp2';
import MoreInfo from './src/components/MoreInfo';
import Page1 from './src/components/Page1';
/**
* This presumes that MyApp2 is the screen that will be loaded first.
* I don't know how you are getting to Page1, but it will be accessible
* if you navigate to it like so:
* this.props.navigation.navigate('Page1')
* Once there, the navigate() in the FlatList of Page1 should work as written.
*/
const RootNavigator = StackNavigator({
MyApp2: {screen: MyApp2},
Page1: {screen: Page1},
MoreInfo: { screen: MoreInfo },
})
AppRegistry.registerComponent('MyApp2', () => RootNavigator);
In your index.android.js file , you are using StackNavigator but you have not imported it .
use :
import { StackNavigator } from react-navigation

Drawer navigator button is not working in react-navigation

I can't get why Button in the HomeScreen is not opening a Drawer. Button shows but nothing happens when you click on it. Here is a code, I did all needed imports while its still not working. Are there any examples of this approach which will work?
HomeDrawer.js
import React from 'react';
import { DrawerNavigator } from 'react-navigation';
import HomeScreen from '../screens/HomeScreen';
import FoodScreen from '../screens/FoodScreen';
import RestaurantsScreen from '../screens/RestaurantsScreen';
import ProfileScreen from '../screens/ProfileScreen';
import FavoritesScreen from '../screens/FavoritesScreen';
import SettingsScreen from '../screens/SettingsScreen';
import SideBar from './SideBar';
const HomeDrawer = DrawerNavigator({
home: { screen: HomeScreen },
food: { screen: FoodScreen },
restaurants: { screen: RestaurantsScreen},
profile: { screen: ProfileScreen },
settings: { screen: SettingsScreen }
}, {
contentComponent: (props) => <SideBar {...props} />
});
export default HomeDrawer;
HomeScreen.js
import React from "react";
import { StatusBar } from "react-native";
import {
Button,
Text,
Container,
Card,
CardItem,
Body,
Content,
Header,
Title,
Left,
Icon,
Right
} from "native-base";
export default class HomeScreen extends React.Component {
render() {
return (
<Container>
<Header>
<Left>
<Button
transparent
onPress={() => this.props.navigation.navigate("DrawerOpen")}>
<Icon name="menu" />
</Button>
</Left>
<Body>
<Title>HomeScreen</Title>
</Body>
<Right />
</Header>
</Container>
);
}
}
How to make that button open a drawer?
try this
<Button transparent onPress={()=>this.props.navigation.openDrawer()}>
Refer to the examples that react-navigation have in their git repo, it is stated there under
react-navigation/examples/NavigationPlayground/js/MultipleDrawer.js

Resources