react-native-router-flux issue cant get scene to change - javascript

I am trying to add a button to get to my settings component (index.js) from my home component(main screen). For some reason this is not working, I have added different screens before and copied them as an example but I am not having any luck with this. I tripled checked the imports and they all seem good.
Here is what my AppNavigator.js looks like:
import React, { Component } from "react";
import { StatusBar, Platform } from "react-native";
import { connect } from "react-redux";
import { Scene, Router } from "react-native-router-flux";
import Login from "./components/common/login/";
import SignIn from "./components/common/signIn/";
import Register from "./components/common/register/";
import DriverStartupService from
"./components/driver/startupServices";
import DriverRootView from "./components/driver/rootView";
import DriverHome from "./components/driver/home";
import RideRequest from "./components/driver/rideRequest";
import PickRider from "./components/driver/pickRider";
import StartRide from "./components/driver/startRide";
import DropOff from "./components/driver/dropOff";
import RateRider from "./components/driver/rateRider";
import Settings from "./components/driver/settings";
import { statusBarColor } from "./themes/base-theme";
import { getAppConfig } from './actions/appConfig';
const RouterWithRedux = connect()(Router);
class AppNavigator extends Component {
static propTypes = {
driverJwtAccessToken: React.PropTypes.string
};
componentWillMount() {
console.log('Getting App Config');
this.props.getAppConfig();
}
render() {
return (
<RouterWithRedux>
<Scene key="root">
<Scene
key="login"
component={Login}
hideNavBar
initial={!this.props.driverJwtAccessToken ? true : false}
/>
<Scene key="signIn" component={SignIn} />
<Scene key="register" component={Register} />
<Scene key="driverRootView" component={DriverRootView}>
<Scene key="driverHome" component={DriverHome} />
<Scene key="rideRequest" component={RideRequest} />
<Scene key="pickRider" component={PickRider} />
<Scene key="startRide" component={StartRide} />
<Scene key="dropOff" component={DropOff} />
<Scene key="rateRider" component={RateRider} />
<Scene key="settings" component={Settings} />
</Scene>
<Scene
key="driverStartupService"
component={DriverStartupService}
hideNavBar
initial={this.props.driverJwtAccessToken}
/>
</Scene>
</RouterWithRedux>
);
}
}
function bindAction(dispatch) {
return {
getAppConfig: () => dispatch(getAppConfig())
};
}
const mapStateToProps = state => ({
driverJwtAccessToken: state.driver.appState.jwtAccessToken
});
export default connect(mapStateToProps, bindAction)(AppNavigator);
Here is the action on my home component (index.js):
import React, { Component } from "react";
import { connect } from "react-redux";
import {
View,
Platform,
TouchableOpacity,
Dimensions,
BackAndroid
} from "react-native";
import {
Content,
Text,
Header,
Button,
Icon,
Title,
Left,
Right,
Body,
Container
} from "native-base";
import { Actions, ActionConst } from "react-native-router-flux";
import {
changePageStatus,
currentLocationDriver
} from "../../../actions/driver/home";
import { logOutUserAsync } from "../../../actions/common/signin";
import styles from "./styles";
import commonColor from "../../../../native-base-
theme/variables/commonColor";
const { width, height } = Dimensions.get("window");
function mapStateToProps(state) {
return {
tripRequest: state.driver.tripRequest,
fname: state.driver.user.fname,
jwtAccessToken: state.driver.appState.jwtAccessToken
};
}
class DriverHome extends Component {
static propTypes = {
logOutUserAsync: React.PropTypes.func,
jwtAccessToken: React.PropTypes.string,
currentLocationDriver: React.PropTypes.func,
openDrawer: React.PropTypes.func
};
constructor(props) {
super(props);
this.state = {
flag: true
};
}
handleLogOut() {
this.props.logOutUserAsync(this.props.jwtAccessToken);
}
componentDidMount() {
BackAndroid.addEventListener("hardwareBackPress", () => {
Actions.pop();
});
}
render() {
// eslint-disable-line class-methods-use-this
return (
<Container>
<Header
androidStatusBarColor={commonColor.statusBarColorDark}
style={styles.iosHeader}
iosBarStyle="light-content"
>
<Left>
<Button transparent>
<Icon
name="ios-power"
style={styles.logoutLogo}
onPress={() => this.handleLogOut()}
/>
</Button>
</Left>
<Body>
<Title
style={
Platform.OS === "ios"
? styles.iosHeaderTitle
: styles.aHeaderTitle
}
>
Hero Home
</Title>
</Body>
<Right>
<Button transparent onPress={() => {
console.log('settings button')
Actions.settings()}}>
<Icon
name="ios-settings"
style={styles.logoutLogo}
/>
</Button>
</Right>
</Header>
<Content />
<View style={styles.detailsContainer}>
<Text style={styles.place}>
Please wait for a Patient request...
</Text>
</View>
<View
style={{
flex: 10,
flexDirection: "row",
alignItems: "flex-end",
justifyContent: "flex-end",
marginRight: 5,
marginTop: height - 150,
marginLeft: width - 40
}}
>
<TouchableOpacity
style={{ flexDirection: "row" }}
onPress={() => this.props.currentLocationDriver()}
>
<Icon name="ios-locate-outline" style={{ fontSize: 40, backgroundColor: 'transparent' }} />
</TouchableOpacity>
</View>
</Container>
);
}
}
function bindActions(dispatch) {
return {
openDrawer: () => dispatch(openDrawer()),
changePageStatus: newPage => dispatch(changePageStatus(newPage)),
logOutUserAsync: jwtAccessToken =>
dispatch(logOutUserAsync(jwtAccessToken)),
currentLocationDriver: () => dispatch(currentLocationDriver())
};
}
export default connect(mapStateToProps, bindActions)(DriverHome);
I can see the console.log message in my terminal so I know the onPress is working.. Any help would be appreciated. Been stuck for hours. I would be happy to share more of the code if needed. Thanks!

Related

How can i add a navigation drawer inside a stack navigator in an already existing project

Hello guys so I wanted to add a navigation DRAWER inside my main screen and I did not know how to nest it with the already existing stack navigator ,
this is my navigation component :
import React from "react";
import { NavigationContainer } from "#react-navigation/native";
import { createStackNavigator } from "#react-navigation/stack";
import ProductsOverviewScreen from "../screens/shop/ProductsOverviewScreen";
import ProductDetails from "../screens/shop/ProductDetailScreen";
import { HeaderButtons,Item } from "react-navigation-header-buttons";
import HeaderButton from '../components/UI/HeaderButton'
import CartScreen from "../screens/shop/CartScreen";
import OrdersScreen from "../screens/shop/OrdersScreen";
const RootNavigation=()=> {
const Stack = createStackNavigator();
const NavigationDrawerStructure = (props)=> {
//Structure for the navigatin Drawer
const toggleDrawer = () => {
//Props to open/close the drawer
props.navigationProps.toggleDrawer();
};
return (
<View style={{ flexDirection: 'row' }}>
<TouchableOpacity onPress={()=> toggleDrawer()}>
{/*Donute Button Image */}
<Image
source={{uri: 'https://raw.githubusercontent.com/AboutReact/sampleresource/master/drawerWhite.png'}}
style={{ width: 25, height: 25, marginLeft: 5 }}
/>
</TouchableOpacity>
</View>
);
}
const screenOptions ={
headerShown:true,
headerStyle: {
backgroundColor: 'white',},
headerTintColor: 'aqua',
headerTitleStyle: {
fontWeight: 'bold',
},
};
return(
<NavigationContainer>
<Stack.Navigator initialRouteName='ProductsOverview' screenOptions={screenOptions}>
<Stack.Screen name='ProductsOverview' component={ProductsOverviewScreen} options={({navigation,route})=>({title:'All Products',headerTitleStyle:{fontFamily:'open-sans-bold'},
headerRight:()=>( <HeaderButtons HeaderButtonComponent={HeaderButton}><Item title ='Cart' iconName='md-cart' onPress={()=>{navigation.navigate('CartScreen')}}/></HeaderButtons>)})}/>
<Stack.Screen name='ProductsDetail' component={ProductDetails} options={({route})=>({title:route.params.productTitle,headerTitleStyle:{fontFamily:'open-sans-bold'}})} />
<Stack.Screen name='CartScreen' component={CartScreen} options={{title:'Cart Items', headerTitleStyle:{fontFamily:'open-sans-bold'}}} />
<Stack.Screen name='OrdersScreen' component={OrdersScreen} options={{title:'Orders '}}/>
</Stack.Navigator>
</NavigationContainer>
)
}
export default RootNavigation;
and this is my app.js
import { StatusBar } from 'expo-status-bar';
import { StyleSheet } from 'react-native';
import {createStore , combineReducers} from 'redux';
import { Provider} from 'react-redux';
import AppLoading from 'expo-app-loading';
import * as Font from 'expo-font';
import productsReducer from './store/reducers/products';
import {composeWithDevTools} from 'redux-devtools-extension'
import RootNavigation from './navigation/ShopNavigation';
import cartReducer from './store/reducers/cart'
import { useState } from 'react';
import ordersReducer from './store/reducers/orders'
const rootReducer=combineReducers({
products: productsReducer,
cart: cartReducer,
orders:ordersReducer,
});
const store = createStore(rootReducer,composeWithDevTools());
const fetchFonts=()=>{
return Font.loadAsync({
'open-sans': require('./assets/fonts/OpenSans-Regular.ttf'),
'open-sans-bold': require('./assets/fonts/OpenSans-Bold.ttf')
})
}
export default function App() {
const [fontLoaded,setfontLoaded]= useState(false);
if (!fontLoaded) {
return (
<AppLoading
startAsync={fetchFonts}
onFinish={()=>setfontLoaded(true)}
onError={console.warn}
/>
);
}
return (
<Provider store={store}>
<RootNavigation />
</Provider>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
can you give me an idea how to nest them together I tried using the docs but still full of errors
and Thanks
Drawer Navigator must be a parent to both Stack and Tab navigators. With that knowledge, let we refactor our code as below:
import React from "react";
import { NavigationContainer } from "#react-navigation/native";
import { createStackNavigator } from "#react-navigation/stack";
import ProductsOverviewScreen from "../screens/shop/ProductsOverviewScreen";
import ProductDetails from "../screens/shop/ProductDetailScreen";
import { HeaderButtons, Item } from "react-navigation-header-buttons";
import HeaderButton from "../components/UI/HeaderButton";
import CartScreen from "../screens/shop/CartScreen";
import OrdersScreen from "../screens/shop/OrdersScreen";
import { createDrawerNavigator } from "#react-navigation/drawer";
const RootNavigation = () => {
const Stack = createStackNavigator();
const Drawer = createDrawerNavigator();
const AppStack = () => (
<Stack.Navigator
initialRouteName="ProductsOverview"
screenOptions={screenOptions}
>
<Stack.Screen
name="ProductsOverview"
component={ProductsOverviewScreen}
options={({ navigation, route }) => ({
title: "All Products",
headerTitleStyle: { fontFamily: "open-sans-bold" },
headerRight: () => (
<HeaderButtons HeaderButtonComponent={HeaderButton}>
<Item
title="Cart"
iconName="md-cart"
onPress={() => {
navigation.navigate("CartScreen");
}}
/>
</HeaderButtons>
),
})}
/>
<Stack.Screen
name="ProductsDetail"
component={ProductDetails}
options={({ route }) => ({
title: route.params.productTitle,
headerTitleStyle: { fontFamily: "open-sans-bold" },
})}
/>
<Stack.Screen
name="CartScreen"
component={CartScreen}
options={{
title: "Cart Items",
headerTitleStyle: { fontFamily: "open-sans-bold" },
}}
/>
<Stack.Screen
name="OrdersScreen"
component={OrdersScreen}
options={{ title: "Orders " }}
/>
</Stack.Navigator>
);
return (
<NavigationContainer>
<Drawer.Navigator>
<Drawer.Screen name="MainStack" component={AppStack} />
</Drawer.Navigator>
</NavigationContainer>
);
};
export default RootNavigation;
I omitted component code below as can't access drawer.
const NavigationDrawerStructure = (props)=> {
//Structure for the navigatin Drawer
const toggleDrawer = () => {
//Props to open/close the drawer
props.navigationProps.toggleDrawer();
};
return (
<View style={{ flexDirection: 'row' }}>
<TouchableOpacity onPress={()=> toggleDrawer()}>
{/*Donute Button Image */}
<Image
source={{uri: 'https://raw.githubusercontent.com/AboutReact/sampleresource/master/drawerWhite.png'}}
style={{ width: 25, height: 25, marginLeft: 5 }}
/>
</TouchableOpacity>
</View>
);
}
Here a minified version of working implementation
https://snack.expo.dev/#emmbyiringiro/69dc5b

How to call a function to main App file? React Native

I have just started learning React Native. I am trying to insert bottom menu tabs on my first app.
I am using this code on Tabs.js (this is just the export part):
export default function Tabs() {
return (
<NavigationContainer>
<MyTabs />
</NavigationContainer>
);
}
Unfortunately, I don't know how to call it to my main App file (this is just one of my attempts):
import * as React from 'react';
import { Text, View } from 'react-native';
import Tabs from './Tabs.js';
Tabs();
I've read about exporting default function, but I don't understand how to use it in my main App file. I'm sure that this is a syntax issue.
Also, I am planning to add a background colour to all tabs. Any advice?
Thank you.
UPDATE:
This is my Tabs file.
import * as React from 'react';
import { Text, View } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import { MaterialCommunityIcons } from '#expo/vector-icons';
const Tabs = () => {
function Feed() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text></Text>
</View>
);
}
function Profile() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text></Text>
</View>
);
}
function MainPage() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text></Text>
</View>
);
}
const Tab = createBottomTabNavigator();
function MyTabs() {
return (
<Tab.Navigator
initialRouteName="Feed"
tabBarOptions={{
activeTintColor: '#e91e63',
}}
>
<Tab.Screen
name="Feed"
component={Feed}
options={{
tabBarLabel: '',
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons name="home" color={color} size={size} />
),
}}
/>
<Tab.Screen
name="MainPage"
component={MainPage}
options={{
tabBarLabel: '',
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons name="pill" color={color} size={size} />
),
}}
/>
<Tab.Screen
name="Profile"
component={Profile}
options={{
tabBarLabel: '',
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons name="format-list-text" color={color} size={size} />
),
}}
/>
</Tab.Navigator>
);
}
return (
<NavigationContainer>
<MyTabs />
</NavigationContainer>
);
}
export default Tabs
This is my main App file.
import * as React from 'react';
import { Text, View } from 'react-native';
import Tabs from './Tabs.js';
const App=()=>{
return <Tabs />
}
Make sure to export the App as default. You most probably have a file called index.js in the root folder and that is importing your App component.
Your App.js file should look like this:
import * as React from 'react';
import { Text, View } from 'react-native';
import Tabs from './Tabs.js';
export default const App=()=>{
return <Tabs />
}
And then your index.js file looks like this:
import {AppRegistry} from 'react-native';
import App from './App';
import {name as appName} from './app.json';
AppRegistry.registerComponent(appName, () => App);
You don't necessarily have to export as default, because you can only have one default export. If you export App as default you import it like this: import App from './App'; and if you export without a default, you have to import like this: import {App} from './App'
And to get an advice how to add background color to the tabs, check here: How to set the background color of Tab.Navigator?
you basically call it like would call a component
btw your Tabs should export like this
const Tabs=()=>{
/...
}
export default Tabs
const App=()=>{
return <Tabs />
}

React native navigation in flatlist

I using the flatlist to display a list of data. I wish to pass the data into another pages, but i have no idea which kind of navigation I shd use.
import Routes from './src/Routes';
export default class App extends Component<Props> {
render() {
return (
<View style={styles.container}>
<StatusBar
backgroundColor="#1c313a"
arStyle="light-content"
/>
<Routes/>
</View>
);
}
}
import React, { Component } from 'react';
import {StyleSheet, View, StatusBar,Text} from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createDrawerNavigator } from '#react-navigation/drawer';
import HomeScreen from '../pages/HomeScreen'
import YourActivitiesScreen from '../pages/YourActivitiesScreen'
import YourFavouriteScreen from '../pages/YourFavouriteScreen'
const Drawer = createDrawerNavigator();
function MyDrawer() {
return (
<Drawer.Navigator initialRouteName="Home">
<Drawer.Screen
name="Home"
component={HomeScreen}
options={{ drawerLabel: 'Home' }}
/>
<Drawer.Screen
name="Your Activities"
component={YourActivitiesScreen}
options={{ drawerLabel: 'Your Activities' }}
/>
<Drawer.Screen
name="Your Favourite"
component={YourFavouriteScreen}
options={{ drawerLabel: 'Your Favourite' }}
/>
</Drawer.Navigator>
);
}
export default function SideMenu() {
return (
<NavigationContainer>
<MyDrawer />
</NavigationContainer>
);
}
import React, { Component } from 'react';
import {Router, Stack, Scene} from 'react-native-router-flux';
import Login from './pages/Login';
import Signup from './pages/Signup';
import SideMenu from './components/SideMenu'
export default class Routes extends Component {
render() {
return(
<Router>
<Stack key="root" hideNavBar>
<Scene key="login" component={Login} title="Login" initial/>
<Scene key="signup" component={Signup} title="Signup" />
<Scene key="home" component={SideMenu} title="HomeScreen" />
</Stack>
</Router>
);
}
}
import React, { Component } from 'react';
import {
StyleSheet,
View,
Text,
AsyncStorage,
TouchableOpacity,
FlatList,
Button,
} from 'react-native';
import DetailsScreen from './Details';
import { createDrawerNavigator, SafeAreaView } from 'react-navigation';
class HomeScreen extends Component{
constructor(props) {
super(props);
this.state = {
activitiesList: [],
}
};
renderItem = (item) => {
return (
<TouchableOpacity
onPress={() => {
console.log('test')
}}
>
<View style={styles.item}>
<Text style={styles.title}>{item.name}</Text>
</View>
</TouchableOpacity>
);
}
render(){
const listActivities = this.state.activitiesList
return (
<View>
<View style={styles.container}>
<Text style={styles.heading}>UPCOMING ACTIVITIES</Text>
</View>
<View>
<SafeAreaView>
<FlatList
data = {listActivities}
renderItem={({ item }) => this.renderItem(item)}
keyExtractor={item => item.id}
/>
</SafeAreaView>
</View>
</View>
)
}
}
I used the react-native-router-flux at the early part of system, which is login, signup and home. Now home display the flatlist, from the flatlist i have to make a onPress to navigate to another pages, the Actions in router-flux that i used before cannot work. Anyone have idea about it? or another better way navigate to to the details of flatlist?
First off, I'd refactor all the code to use just one kind of navigator (in this case, going for react-navigation). So, we will have your router-flux code combined with your
//Your routes screen
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
//... add missing imports
const Stack = createStackNavigator();
//this will be your old router-flux
const Root = () => {
return (
<Stack.Navigator>
<Stack.Screen name="login" component={Login} title="Login" initial/>
<Stack.Screen name="signup" component={Signup} title="Signup" />
<Stack.Screen name="home" component={SideMenu} title="HomeScreen" />
</Stack.Navigator>
)
}
const Drawer = () => {
return (
<Drawer.Screen
name="Home"
component={HomeScreen}
options={{ drawerLabel: 'Home' }}
/>
<Drawer.Screen
name="Your Activities"
component={YourActivitiesScreen}
options={{ drawerLabel: 'Your Activities' }}
/>
<Drawer.Screen
name="Your Favourite"
component={YourFavouriteScreen}
options={{ drawerLabel: 'Your Favourite' }}
/>
</Drawer.Navigator>
)
}
const AppContainer = () => {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Root" component={Root} />
<Stack.Screen name="Drawer" component={Drawer} />
//import your Details screen to use inside component
<Stack.Screen name="Details" component={Details} />
</Stack.Navigator>
</NavigationContainer>
);
}
export default AppContainer
You will wrap your App.js component with this AppContainer. What we just did was to nest the navigations, your Home will be reached first and your drawer will be all in the same. Also, there is one missing stack in your code that is the one for the Details.
Right after here you are going to use all the actions from react-navigation. All the screens will receive a navigation props. Once you want to navigate from your Root, you will call the navigation just like props.navigation.navigate("Home").
The same will apply to navigate to your Detail screen from the FlatList.
//Your Home Screen
import React, { Component } from 'react';
import {
StyleSheet,
View,
Text,
AsyncStorage,
TouchableOpacity,
FlatList,
Button,
SafeAreaView
} from 'react-native';
class HomeScreen extends Component{
constructor(props) {
super(props);
this.state = {
activitiesList: [],
}
};
renderItem = (item) => {
return (
<TouchableOpacity
onPress={() => {
props.navigation.navigate("Details", { data: item })
console.log('test')
}}
>
<View style={styles.item}>
<Text style={styles.title}>{item.name}</Text>
</View>
</TouchableOpacity>
);
}
render(){
const listActivities = this.state.activitiesList
return (
<View>
<View style={styles.container}>
<Text style={styles.heading}>UPCOMING ACTIVITIES</Text>
</View>
<View>
<SafeAreaView>
<FlatList
data = {listActivities}
renderItem={({ item }) => this.renderItem(item)}
keyExtractor={item => item.id}
/>
</SafeAreaView>
</View>
</View>
)
}
}
Just added the navigation action to the code above. You have to access the params object in your Details Screen
//Details Screen
class DetailsScreen extends React.Component {
render() {
const { routes } = this.props;
return (
<View>
//Your component
<Text>{routes.data.name}</Text>
</View>
);
}
}
Just a side note. If you have a problem when navigating to a nested stack you can navigate this way using params
navigation.navigate(<YourParent>, {
screen: <YourDesiredScreen>,
params: { <YourObject> },
});
I hope it helps, at least as a guide. I didn't tested it, that's why I asked you to upload your code to expo.
I use react-navigation and couldn't be happier. All the navigation needed can be done with a simple:
this.props.navigation.navigate('ScreenName', {param1: 'Hello', param2: 'World'})
and then, when on the screen desired, get the param:
const { param1, param2 } = this.props.route.params;
More details here.
And, of course, if using function components it is even easier.
This example is form my 1st react-native-expo project but I hope that it will help you.
Bottom code is for two stack screens where I have PlayersTab screen and Player so main focus is to access Player with parms from PlayersTab using react-navigation
Navigation is in props object all you need is to destructor it in component const PlayersList = ({ navigation }) => {//your code}
import { View, Text } from 'react-native';
import React from 'react';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import PlayersList from '../personal_data_screen/PlayersList';
import PersonalDataScreenPlayer from'../personal_data_screen/PersonalDataScreenPlayer';
const Stack = createNativeStackNavigator();
const PersonalPlayerDataNavigator = ({ loginDataObject }) => {
return (
<Stack.Navigator>
<Stack.Screen options={{ headerShown: false }} name='PlayersTab'>
{(props) => (
<PlayersList {...props} loginDataObject={loginDataObject} />
)}
</Stack.Screen>
<Stack.Screen options={{ headerShown: false }} name='Player'>
{(props) => <PersonalDataScreenPlayer {...props} />}
</Stack.Screen>
</Stack.Navigator>
);
};
export default PersonalPlayerDataNavigator;
FlatList witch is in PlayersTab looks like this
<FlatList
data={Object.keys(friendList.data)}
renderItem={renderItem}
keyExtractor={keyExtractor}
navigation={navigation}
/>
const renderItem = ({ item }) => (
<Item
navigation={navigation}
account_id={friendList.data[item].account_id}
nickname={friendList.data[item].nickname}
/>
const Item = ({ nickname, account_id, navigation }) => (
<TouchableOpacity
onPress={() => navigation.navigate('Player', { account_id: account_id })}>
<View style={styles.itemView}>
<Text style={styles.playerNicknameText}>{nickname}</Text>
</View>
</TouchableOpacity>
And code for Player screen
import React from 'react';
import { View, Text } from 'react-native';
const PersonalDataScreenPlayer = ({ route }) => {
return (
<View
style={{
flex: 1,
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
}}>
<Text>{route.params.account_id}</Text>
</View>
);
};
export default PersonalDataScreenPlayer;

React native - Maximum call stack size exceeded

When I add the <Menu /> component to my header as below:
let SearchPage = (props) => {
const menu = (
<Container>
<Header style={styles.header}>
<Left>
<Button >
<Menu />
</Button>
</Left>
<Body>
I get the error
Maximum call stack size exceeded
and of course if I comment out the <Menu /> line in my SearchPage, there is no error.
The menu is a react-native-off-canvas-menu
My menu component:
components/menu/Menu.js
import React from 'react'
import { View, Icon } from 'react-native'
import { connect } from 'react-redux'
import { togglePageMenu } from './menu.action'
import { OffCanvas3D } from 'react-native-off-canvas-menu'
//import AddPage from '../add-page/AddPage'
import SearchPage from '../search-page/SearchPage'
const mapStateToProps = (state) => ({
isOpen: state.get('menu').isOpen
})
const mapDispatchToProps = (dispatch) => ({
togglePageMenu: () => {
dispatch(togglePageMenu())
}
})
let Menu = (props) => (
<View style={{ flex: 1 }}>
<OffCanvas3D
active={props.isOpen}
onMenuPress={props.togglePageMenu}
backgroundColor={'#222222'}
menuTextStyles={{ color: 'white' }}
handleBackPress={true}
menuItems={[
{
title: 'Search Products',
icon: <Icon name="camera" size={35} color='#ffffff' />,
renderScene: <SearchPage />
}
]} />
</View>
)
Menu.propTypes = {
togglePageMenu: React.PropTypes.func.isRequired,
isOpen: React.PropTypes.bool.isRequired
}
Menu = connect(
mapStateToProps,
mapDispatchToProps
)(Menu)
export default Menu
What could be causing the error?
Here is my component that uses the menu (probably not relevant):
components/search-page/SearchPage.js
import { ScrollView, StyleSheet, View } from 'react-native'
import {
Container,
Button,
Text,
Header,
Body,
Right,
Left,
Title,
Icon
} from 'native-base'
import React from 'react'
import Keywords from '../keywords/Keywords'
import Categories from '../categories/Categories'
import Location from '../location/Location'
import Menu from '../menu/Menu'
import DistanceSlider from '../distanceSlider/DistanceSlider'
import Map from '../map/Map'
import Drawer from 'react-native-drawer'
import { connect } from 'react-redux'
import { toggleMenu } from './searchPage.action'
import { styles, wideButtonColor } from '../../style'
import searchPageStyle from './style'
import { selectIsSearchFormValid } from './isSearchFormValid.selector'
const mapStateToProps = (state) => ({
isMenuOpen: state.get('searchPage').get('isMenuOpen'),
isSearchFormValid: selectIsSearchFormValid(state)
})
const mapDispatchToProps = (dispatch) => ({
toggleMenu: () => {
dispatch(toggleMenu())
}
})
let SearchPage = (props) => {
const menu = (
<Container>
<Header style={styles.header}>
<Left>
<Button >
<Menu />
</Button>
</Left>
<Body>
<Title style={styles.title}>Search Products</Title>
</Body>
<Right>
</Right>
</Header>
<Container style={styles.container}>
<ScrollView keyboardShouldPersistTaps={true}>
<Categories />
<View style={searchPageStyle.locationContainer}>
<Location />
</View>
<DistanceSlider />
<Keywords />
<Button
block
style={{
...searchPageStyle.goButton,
backgroundColor: wideButtonColor(!props.isSearchFormValid)
}}
disabled={!props.isSearchFormValid}
onPress={props.toggleMenu}>
<Text>GO</Text>
</Button>
</ScrollView>
</Container>
</Container>
)
return (
<Drawer open={props.isMenuOpen} content={menu}>
<Container style={mapStyles.container}>
<Map />
</Container>
</Drawer>
)
}
SearchPage.propTypes = {
toggleMenu: React.PropTypes.func.isRequired,
isMenuOpen: React.PropTypes.bool.isRequired,
isSearchFormValid: React.PropTypes.bool.isRequired
}
SearchPage = connect(
mapStateToProps,
mapDispatchToProps
)(SearchPage)
export default SearchPage
const mapStyles = StyleSheet.create({
container: {
...StyleSheet.absoluteFillObject,
height: 400,
width: 400,
justifyContent: 'flex-end',
alignItems: 'center',
}
})
It's because you are rendering another <SearchPage /> within your menu: renderScene: <SearchPage />. This creates a circular dependency where a SearchPage is creating a Menu and the Menu is creating a SearchPage... etc. Until, as you saw, you run out of memory.

Pass parameters from component to component in React Native

I'm making an aplication using router flux. Everything works fine until I encountered this problem. I don't know how can i pass a function with some parameters from the a form, to the toolbar (where the user should press the send button). Here is the where the router is defined:
export default class App extends Component {
render() {
return (
<Router>
<Scene key="root" hideNavBar={true}>
<Scene key="SplashPage" component={SplashPage} initial={true} panHandlers={null}/>
<Scene key="drawer" component={NavigationView} open={false} direction="vertical">
<Scene key="main" hideNavBar={false}>
<Scene key="MainPage" component={MainPage} search="" title={I18n.t("nautal")} mainIcon="menu" secondaryIcon={["search"]} mainAction={()=>Actions.refresh({key: 'drawer', open: value => !value })} secondaryAction={()=>Actions.SearchBoatsPage()} navBar={MyToolbar} panHandlers={null}/>
<Scene key="CheckListPage" component={CheckListPage} title={I18n.t("checklist")} navBar={MyToolbarEmpty} panHandlers={null}/>
<Scene key="MeteoPage" component={MeteoPage} title={I18n.t("meteo")} mainIcon="menu" secondaryIcon={["search","done"]} navBarSearch={true} mainAction={()=>Actions.refresh({key: 'drawer', open: value => !value })} navBar={MyToolbar} panHandlers={null}/>
<Scene key="InfoPortsPage" component={InfoPortsPage} title={I18n.t("infoPorts")} navBar={MyToolbar} mainIcon="menu" secondaryIcon={["search","done"]} mainAction={()=>Actions.refresh({key: 'drawer', open: value => !value })} navBarSearch={true} panHandlers={null}/>
<Scene key="ToolsPage" component={ToolsPage} title={I18n.t("tools")} navBar={MyToolbarEmpty} panHandlers={null}/>
<Scene key="SearchBoatsPage" component={SearchBoatsPage} title={I18n.t("searchBoats")} mainIcon="arrow-back" secondaryIcon={["done"]} mainAction={()=>Actions.pop()} secondaryAction={()=>Actions.MainPage()} navBar={MyToolbar} panHandlers={null}/>
<Scene key="CompassPage" component={CompassPage} title={I18n.t("compass")} navBar={MyToolbarEmpty} panHandlers={null}/>
<Scene key="MOBPage" component={MOBPage} title={I18n.t("manOverboard")} navBar={MyToolbarEmpty} panHandlers={null}/>
</Scene>
</Scene>
</Scene>
</Router>
)
}
}
Here is the toolbar component (with the send button):
import React, { Component } from 'react';
import {StyleSheet, View, Text, TextInput, Dimensions} from 'react-native';
import {Toolbar} from 'react-native-material-design';
import I18n from '../core/Translations';
import Icon from 'react-native-vector-icons/MaterialIcons';
import { Kohana } from 'react-native-textinput-effects';
import { Actions } from 'react-native-router-flux';
var {height, width} = Dimensions.get('window');
class MyToolbar extends Component {
constructor(props) {
super(props);
this.state = {
tabBarSearch: false,
counter: false,
secondIcon: this.props.secondaryIcon[0]
};
this.pressButton = this.pressButton.bind(this);
}
pressButton() {
if(typeof this.props.secondaryAction!="undefined"){
this.props.secondaryAction();
}
if(this.props.navBarSearch){
var icon = (!this.state.counter) ? this.props.secondaryIcon[1] : this.props.secondaryIcon[0];
this.setState({
tabBarSearch: !this.state.tabBarSearch,
secondIcon: icon,
counter: !this.state.counter
});
}
}
render() {
return (
<View style={{position: 'absolute', top: 0, flex: 1, alignSelf: 'stretch', right: 0, left: 0}}>
<Toolbar
title={(this.state.tabBarSearch) ? null : this.props.title}
icon={this.props.mainIcon}
onIconPress= {this.props.mainAction}
actions={[{
icon: this.state.secondIcon,
onPress: this.pressButton
}]}
overrides={{backgroundColor: '#015B83'}}
rightIconStyle={{
margin: 10
}}
>
<Kohana
style={{ backgroundColor: '#015B83' }}
iconClass={Icon}
iconName={'search'}
iconColor={'white'}
labelStyle={{ color: 'white', fontSize: 20}}
inputStyle={{ color: 'white', fontSize: 20, fontWeigth:'bold' }}
autoFocus={true}
placeholder={'Search'}
placeholderTextColor ={'#aaa'}
/>
</Toolbar>
</View>
)
}
}
module.exports = MyToolbar;
and here is the form( where the user imputs data to send):
import React, { Component } from 'react';
import { View, Text, StatusBar, Dimensions, ScrollView } from 'react-native';
import { Actions } from 'react-native-router-flux';
import DrawerLayout from 'react-native-drawer-layout';
import TextField from 'react-native-md-textinput';
import {Button } from 'react-native-material-design';
import NavigationView from '../Components/NavigationView';
import MyToolbarEmpty from '../Components/MyToolbarEmpty';
import MyToolbar from '../Components/MyToolbar';
import I18n from '../core/Translations';
import STYLES from '../core/Styles';
import GLOBAL from '../core/Global';
var {height, width} = Dimensions.get('window');
export default class SearchBoatsPage extends Component {
constructor(props) {
super(props);
this.state = {
country:'',
area:'',
duration:'',
startDate:''
};
this.searchData = this.searchData.bind(this);
}
searchData(){
var search = {country:this.state.country, area:this.state.area, duration:this.state.duration, startDate:this.state.startDate};
Actions.MainPage({search: search});
}
render() {
const goToPageTwo = () => Actions.CheckListPage({text: 'Hello World!'});
const openDrawer = () => Actions.refresh({key: 'drawer', open: value => !value });
return (
<View>
<StatusBar
hidden={false}
backgroundColor='#096f9c'
/>
<ScrollView>
<View style={STYLES.container}>
<View style={STYLES.subContainer}>
<TextField onChangeText={country => this.setState({country})} label={ I18n.t("country") } highlightColor={'#08AE9E'} value={this.state.country}/>
<TextField onChangeText={area => this.setState({area})} label={ I18n.t("area") } highlightColor={'#08AE9E'} value={this.state.area}/>
<TextField onChangeText={duration => this.setState({duration})} label={ I18n.t("duration") } highlightColor={'#08AE9E'} value={this.state.duration}/>
<TextField onChangeText={startDate => this.setState({startDate})} label={ I18n.t("startDate") } highlightColor={'#08AE9E'} value={this.state.startDate}/>
</View>
<View style={STYLES.bottomButton}>
<Button
onPress={this.searchData}
text={ I18n.t("search") }
theme = 'dark'
textColor = 'white'
raised={true}
overrides={{backgroundColor: '#08AE9E', rippleColor:'#39beb1'}}
/>
</View>
</View>
</ScrollView>
</View>
)
}
_setDrawer() {
this.refs['DRAWER'].openDrawer();
}
}
To summarise, i want to send parameters from the form to the toolbar, so i will be able to send the form info by pressing the button on the toolbar.

Categories