Yes, I've read multiple threads on this topic but I still can't get my project to work: In My App.js I have a conditional rendering of a Login Screen or to render the Screen. This is also where my AppContainer lives. The method handleAddSubmit=()=>{} triggered by a button in my Header gives me the undefined error. Any suggestions?
App.js
return(
<View>
<AppNav/>
<Main
username={this.state.username}
onLoggedOut={this.LoggedOut}
/>
</View>
);
Main.js
import React from 'react';
import { StyleSheet, Text, View, Platform, ScrollView} from 'react-native';
import { Header} from 'react-native-elements';
import IntervalSelector from './HourCards/IntervalSelector'
import HourCard from './HourCards/HourCard'
export default class Main extends React.Component {
constructor(props){
super(props);
}
handleAddSubmit = () =>
{
this.props.navigation.navigate('ToggleNewHourFile');
}
render() {
const {username} = this.props;
return (
<View>
<Header
centerComponent={{ text: '[ ' + username + ' ]',
style: { color: '#fff',
fontFamily: Platform.OS === 'ios' ? 'AppleSDGothicNeo-UltraLight' : 'Roboto',
fontSize:20 } }}
backgroundColor='#18153f'
rightComponent=
{{
icon: 'home',
color: '#fff',
onPress: this.handleHomeSubmit,
underlayColor: 'transparent',
}}
leftComponent=
{{
icon: 'add',
color: '#fff',
onPress: this.handleAddSubmit,
underlayColor: 'transparent',
}}
statusBarProps={{barStyle:"light-content", translucent:'true'}}
/>
<IntervalSelector/>
<View>
<ScrollView>
<HourCard/>
</ScrollView>
</View>
</View>
);
}
}
StackNavigator.js
import {createStackNavigator, createAppContainer} from 'react-navigation';
import Main from '../main/Main';
import ToggleNewHourFile from '../main/HourCards/ToggleNewHourFile';
const StackNavigator = createStackNavigator(
{
Main: { screen: Main },
ToggleNewHourFile: {screen: ToggleNewHourFile},
}
);
const AppNav = createAppContainer(StackNavigator);
export default AppNav;
ToggleNewHourFile.js
import React from 'react';
import { StyleSheet, Text, View, Platform, TouchableOpacity, Image} from 'react-native';
class ToggleNewHourFile extends React.Component{
render(){
return(
<Text>Hallo</Text>
)
}
}
export default ToggleNewHourFile;
You reference Main in your stack navigator and also in your App.js. The Main in App.js does not have access to the stack navigator which is what's causing the error.
You can explicitly pass the navigator as a prop to Main, for example:
navigator;
...
<View>
<AppNav ref={nav => this.navigator = nav}/>
<Main
navigation={this.navigator}
username={this.state.username}
onLoggedOut={this.LoggedOut}
/>
or you can refactor your code to remove the Main component from App.js
Related
I have a big problem with my code at the moment, and I know, there is a lot of request with the same issue as mine. I tried a lot of the solutions, but NOTHING helped.
Maybe someone can help me :)
I get the issue in the Title mentionend:
Error: The component for route 'Home' must be a React component. For
example:
import MyScreen from './MyScreen'; ... Home: MyScreen, }
You can also use a navigator:
import MyNavigator from './MyNavigator'; ... Home: MyNavigator, }
This is my code in the specified files:
App.js
import React from 'react'; import { View, Text, Button } from 'react-native'; import { createAppContainer } from 'react-navigation'; import { createStackNavigator } from 'react-navigation-stack';
import Home from './src/Home'; import Profile from './src/Profile';
const Navigator = createStackNavigator({ Home: { screen: Home }, Profile: { screen: Profile }, }, { initialRouteName: 'Home', });
const App = createAppContainer(Navigator);
export default App;
Home.js
import React from 'react'; import { StyleSheet, View, Button } from 'react-native';
export default class Home extends React.Component {
static navigationOptions = {
title: 'Home', };
render() {
const { navigate } = this.props.navigation;
return (
<View style={styles.container}>
<Button
title="Go to profile screen"
onPress={() => navigate(
'Profile', { name: 'Jane' }
)}
/>
</View>
);
}
}
const styles = StyleSheet.create({ container: { flex: 1, alignItems: 'center', justifyContent: 'center' } });
Profile.js
import React, { Component } from 'react';
import { StyleSheet, View, Text, Button } from 'react-native';
export default class Profile extends React.Component {
static navigationOptions = ({ navigation }) => {
return {
title: navigation.getParam('name'),
};
};
render() {
const { navigate, state } = this.props.navigation;
return (
<View style={styles.container}>
<Text>Hello {state.params.name}</Text>
<Button
title="Go to home screen"
onPress={() => navigate('Home')}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center'
}
});
Please make sure that you are having the following structure in your project:
App.js in your project folder. Home.js and Profile.js in the src folder.
App.js (in ./ folder)
import React from 'react';
import { View, Text, Button } from 'react-native';
import { createAppContainer } from 'react-navigation';
import { createStackNavigator } from 'react-navigation-stack';
import Home from './src/Home';
import Profile from './src/Profile';
const Navigator = createStackNavigator({ Home: { screen: Home }, Profile: { screen: Profile }, }, { initialRouteName: 'Home', });
const App = createAppContainer(Navigator);
export default App;
Home.js (in ./src folder)
import React from 'react'; import { StyleSheet, View, Button } from 'react-native';
export default class Home extends React.Component {
static navigationOptions = {
title: 'Home', };
render() {
const { navigate } = this.props.navigation;
return (
<View style={styles.container}>
<Button
title="Go to profile screen"
onPress={() => navigate(
'Profile', { name: 'Jane' }
)}
/>
</View>
);
}
}
const styles = StyleSheet.create({ container: { flex: 1, alignItems: 'center', justifyContent: 'center' } });
Profile.js (in ./src folder)
import React, { Component } from 'react';
import { StyleSheet, View, Text, Button } from 'react-native';
export default class Profile extends React.Component {
static navigationOptions = ({ navigation }) => {
return {
title: navigation.getParam('name'),
};
};
render() {
const { navigate, state } = this.props.navigation;
return (
<View style={styles.container}>
<Text>Hello {state.params.name}</Text>
<Button
title="Go to home screen"
onPress={() => navigate('Home')}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center'
}
});
If you place all the files correctly, it will WORK.
Please click the link below to see the result:
http://www.createchhk.com/2020_12_30_01_56_22.mp4
I'm having an issue with my react-navigation-stack, I believe it could be a problem with dependencies, but I'm not sure if that's it. I am simply trying to have some text redirect to another page. If there is code that is irrelevant to the issue, such as a button, I apologize as I am trying to learn react native. The problem is being pointed at homeStack.js at the first import, "import { createStackNavigator } from '#react-navigation/stack';" , but previously I just used react-navigation-stack there, which I believe was a part of old dependencies, but it gave me a module not found error at first, which changed to what I have now when I put #react-navigation/stack instead. I was learning from a video tutorial, but the code from the tutorial was not compiling. I redownloaded react navigation multiple times and have tried some thing that did not work. I will post my code below and would really appreciate help and input as to what can help my problem. Thanks you!
Picture of error
homeStack.js
import { createStackNavigator } from '#react-navigation/stack';
//import { createAppContainer } from '#react-navigation/native';
//import { createStackNavigator } from 'react-navigation-stack';
import { createAppContainer } from 'react-navigation';
import Home from '../screens/home';
import ReviewDetails from '../screens/reviewDetails';
const screens = {
Home: {
screen: Home,
},
ReviewDetails: {
screen: ReviewDetails,
},
};
// home stack navigator screens
const HomeStack = createStackNavigator(screens);
export default createAppContainer(HomeStack);
home.js
import React from 'react';
import { StyleSheet, View, Text, } from 'react-native';
import { globalStyles } from '../styles/global';
export default function Home() {
return (
<View style={globalStyles.container}>
<Text style={globalStyles.titleText}>Home Screen</Text>
</View>
);
}
App.js
//import React from 'react';
import React, { Component } from 'react';
import { StyleSheet, Text, View, Image, Button } from 'react-native';
import Buttonwithbackground from './src/Buttonwithbackground';
import { StackNavigator } from 'react-navigation';
//import Expo from 'expo';
//import Screen from 'screen2';
import { AppLoading } from 'expo';
import Navigator from './routes/homeStack';
import { render } from 'react-dom';
//
//import {Link} from 'react-router-dom';
class HomeScreen extends React.Component{
static NavigationOptions = {
title: 'Home',
};
render(){
const { navigate} = this.props.navigation;
return(
<View style={styles.container}>
<Text
onPress= { ()=> navigate('Home') }>Navigate to Profile
</Text>
</View>
);
}
}
class ProfileScreen extends React.Component{
static NavigationOptions = {
title: 'Profile',
};
render(){
const { navigate} = this.props.navigation;
return(
<View style={styles.container}>
<Text
onPress= { ()=> navigate('Profile') }>Navigate to Profile
</Text>
</View>
);
}
}
//export default function App() {
export default class App extends Component {
editUser = () => {
this.props.navigation.navigate("Screen");
// this.navigation.navigate("screen2");
// window.location.href = 'screen2';
};
editUser2 = () => {
//if the second button is clicked, it will redirect to yahoo.com
window.location.href="http://yahoo.com"
};
render(){
return (
<View style={styles.container}>
<Image
style={{width: 350, height: 200}}
source = {require('./assets/dolanduckjoker.jpg')}
/>
<Navigator />
<Buttonwithbackground text='Login' color='black' onPress={this.editUser2}/>
<p><br/></p>
<Button title='Login' color='black' onPress={this.editUser2}/>
<Button title='Login' color='black' onPress={() => navigation.navigate('screen2.js')}/>
<p><br/></p>
<Button
style={styles.cancelButton}
onPress={this.editUser}
title="Register"
color="#343434"
accessibilityLabel="Register a User."/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'white',
alignItems: 'center',
justifyContent: 'center',
},
title: {
fontSize: 32,
textAlign: 'center',
margin: 10,
},
});
The error says what's wrong -
Object(...) is not a function
createStackNavigator expects a function and you are passing an object to it as a parameter. According to docs
Your code should look like -
import { createStackNavigator } from '#react-navigation/stack';
//import { createAppContainer } from '#react-navigation/native';
//import { createStackNavigator } from 'react-navigation-stack';
import { createAppContainer } from 'react-navigation';
import Home from '../screens/home';
import ReviewDetails from '../screens/reviewDetails';
const Stack = createStackNavigator();
function MyStack() {
return (
<Stack.Navigator>
<Stack.Screen name="Home" component={Home} />
<Stack.Screen name="ReviewDetails" component={ReviewDetails} />
</Stack.Navigator>
);
}
export default MyStack; //you need to render this
Now in your root file, It should be something like this (excluding your additional code) -
import { createStackNavigator } from '#react-navigation/stack';
import MyStack from "yourPath";
export default function App() {
return (
<NavigationContainer>
<MyStack />
</NavigationContainer>
);
}
I am new to react native and I have been trying to create a header and pull out menu using createDrawerNavigator.
When running my code I get the following error.
Error: The component for route 'Home' must be a React component. For example:
import MyScreen from './MyScreen';
Home: MyScreen,
}
You can also use a navigator:
import MyNavigator from './MyNavigator';
Home: MyNavigator,
}
Here is my app.js file:
import React from 'react';
import { Button, View, Text } from 'react-native';
import { createAppContainer } from 'react-navigation';
import MyDrawerNavigator from './components/MyDrawerNavigator';
const MyApp = createAppContainer(MyDrawerNavigator);
export default class App extends React.Component {
render() {
return <MyApp />;
}
}
My HomeScreen.js file
import React from 'react';
import { Text, Button } from 'react-native';
import LogoTitle from './LogoTitle';
class MyHomeScreen extends React.Component {
static navigationOptions = ({ navigation }) => {
return {
headerTitle: <LogoTitle />,
headerLeft: (
<Button
onPress={() => this.props.navigation.navigate('DrawerToggle')}
title={'Menu'}
/>
),
};
};
render() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
</View>
);
}
}
export default MyHomeScreen;
My MyDrawerNavigator.js file
import React from 'react';
import { Button, Platform, Image, View, Text } from 'react-native';
import { createDrawerNavigator } from 'react-navigation-drawer';
import MyHomeScreen from './HomeScreen';
import DetailsScreen from './DetailScreen';
const MyDrawerNavigator = createDrawerNavigator(
{
Home: MyHomeScreen,
Details: DetailsScreen,
}, {
drawerPosition: 'right',
contentOptions: {
activeTintColor: '#000',
},
});
export default MyDrawerNavigator
The are 2 problems here:
1) You are not exporting your MyDrawerNavigator just add:
export default MyDrawerNavigator
to your MyDrawerNavigator.js file
2) You are not exporting your HomeScreen. You'll have to create a separate file for it, like you did with DetailsScreen.
The HomeScreen.js file would look like:
class MyHomeScreen extends React.Component {
static navigationOptions = ({ navigation }) => {
return {
headerTitle: <LogoTitle />,
headerLeft: (
<Button
onPress={() => this.props.navigation.navigate('DrawerToggle')}
title={'Menu'}
/>
),
};
};
render() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
</View>
);
}
}
You NEED to add a render inside of your screens
Am trying to start playing with React Native now. And I come from web development field.
Since start, am trying to organize my folder structure so that it would be easy for me to understand and make modifications later.
Right now the folder structure is as follows:
/screens
HomeScreen.js
ProfileScreen.js
/navigation
MainNavigation.js
App.js
... etc
Am using Expo CLI as this is my first time working on React Native.
/navigation/MainNavigation.js
import React from 'react';
import { createStackNavigator, createAppContainer } from 'react-navigation';
import HomeScreen from '../screens/HomeScreen';
import ProfileScreen from '../screens/ProfileScreen';
const RootStack = createStackNavigator(
{
Home: HomeScreen,
Profile: ProfileScreen,
},
{
initialRouteName: 'Home',
}
);
const AppContainer = createAppContainer(RootStack);
export default class Navigation extends React.Component {
render() {
return (
<AppContainer />
);
}
}
/screens/HomeScreen.js
import React from 'react';
import { StyleSheet, Text, View, Button, TouchableOpacity } from 'react-native';
export default function HomeScreen() {
return (
<View style={styles.container}>
<TouchableOpacity style={styles.blue_btn} onPress={() => this.props.navigation.navigate('Profile')}>
<Text style={styles.white_text}>Profile</Text>
</TouchableOpacity>
<Text>Open up App.js to start working on your app!</Text>
</View>
);
}
HomeScreen.navigationOptions = {
header: null,
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
blue_btn: {
backgroundColor: '#13baa8',
padding: 10,
},
white_text: {
color: 'white',
}
});
/screens/ProfileScreen.js
import React from 'react';
import { StyleSheet, Text, View, Button } from 'react-native';
export default function ProfileScreen() {
return (
<View style={styles.container}>
<Text>Open up App.js to start working on your app!</Text>
</View>
);
}
ProfileScreen.navigationOptions = {
title: 'Profile',
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
App.js
import React from 'react';
import Navigation from './navigation/MainNavigation';
export default class App extends React.Component {
render() {
return (
<Navigation />
);
}
}
When I click on the Profile button in the HOME Screen, it is showing this message:
undefined is not an object(evaluating '_this.props.navigation')
Thank you
import React, { Component } from 'react';
import { createStackNavigator, createAppContainer } from 'react-navigation';
import ScreenOne from './ScreenOne';
import ScreenTwo from './ScreenTwo';
const NavStack = createStackNavigator({
ScreenOne: {
screen: ScreenOne,
},
ScreenTwo: {
screen: ScreenTwo,
},
});
const App = createAppContainer(NavStack);
export default App;
I'm currently figuring out how to reuse a navigation which is declared in it's own class for multiple screens or to put it in another way: If my approach isn't clever react wise, is there another, better way to create a navigation that is reused on multiple screens?
Whenever I'm trying to click a button in the navigation I get an error "undefined is not an object (evaluating _this2.props.navigation.navigate). So I guess that I'm missing something about this.props in the Navigation.js.
I'm using react-navigation because it has been recommended on SO and in the react-native documentation as the way to go.
App.js
import React from 'react';
import {createStackNavigator} from 'react-navigation';
import HomeScreen from './screens/home/HomeScreen'
import ProfileScreen from './screens/profile/ProfileScreen'
import SettingsScreen from './screens/settings/SettingsScreen'
const RootStack = createStackNavigator(
{
Home: HomeScreen,
Profile: ProfileScreen,
Settings: SettingsScreen,
},
{
initialRouteName: 'Home',
}
);
export default class App extends React.Component {
render() {
return <RootStack />;
}
}
Navigation.js - contains the planned navigation for all screens
import React from 'react';
import {StyleSheet, View, TouchableOpacity, Text} from 'react-native';
class Navigation extends React.Component {
render() {
return (
<View style={navigationStyles.footerWrapper}>
<View style={navigationStyles.footer}>
<TouchableOpacity style={navigationStyles.footerItem}
onPress={() => this.props.navigation.navigate('Home')}>
<Text style={navigationStyles.placeholderIcon}/>
</TouchableOpacity>
<TouchableOpacity style={navigationStyles.footerItem}
onPress={() => this.props.navigation.navigate('Profile')}>
<Text style={navigationStyles.placeholderIcon}/>
</TouchableOpacity>
<TouchableOpacity style={navigationStyles.footerItem}
onPress={() => this.props.navigation.navigate('Settings')}>
<Text style={navigationStyles.placeholderIcon}/>
</TouchableOpacity>
</View>
</View>
);
}
}
const navigationStyles = StyleSheet.create({
//
});
module.exports = Navigation;
HomeScreen.js - screen that should contain the navigation but displays an error when the onPress event is fired
import React from 'react';
import {StyleSheet, View, TouchableOpacity, Text} from 'react-native';
import styles from '../../common/customStyleSheet'
import Navigation from '../../components/navigation/Navigation';
class HomeScreen extends React.Component {
static navigationOptions = {
title: 'Home',
header: null,
};
render() {
const {navigate} = this.props.navigation;
return (
<View style={styles.container}>
<Text style={homeScreenStyles.paddingMedium}>HomeScreen.</Text>
<Navigation/>
</View>
);
}
}
const homeScreenStyles = StyleSheet.create({
paddingMedium: {
paddingTop: 200,
},
});
module.exports = HomeScreen;
your Navigation component won't automatically inherit the navigation prop from HomeScreen because it is just a subcomponent (it is not defined in the stack navigator like the HomeScreen is). So you need to pass the navigation as a prop to the Navigation component in your HomeScreen JSX.
// HomeScreen.js
render() {
return (
<View style={styles.container}>
<Text style={homeScreenStyles.paddingMedium}>HomeScreen.</Text>
<Navigation navigation={this.props.navigation}/>
</View>
);
}