I'm trying to make custom component here (footer). Here's my code:
Footer.js
import React, { Component } from 'react'
import {
View,
Text,
Linking,
StyleSheet,
Image,
TouchableOpacity
Dimensions,
} from 'react-native'
class Footer extends Component {
constructor(props) {
super(props);
}
static navigationOptions = ({ navigation }) => ({
title: ''
})
_pageAbout = () => {
this.props.navigation.navigate('About');
}
render() {
return (
<View>
<View style={{ margin: 15 }}>
<TouchableOpacity
onPress={()=>this._pageAbout()}>
<Text>About</Text>
</TouchableOpacity>
</View>
</View>
);
}
}
export default Footer
Then I import and call that component on Home.js screen.
Home.js
import React, { Component } from 'react'
import {
View,
Text,
Linking,
StyleSheet,
Image,
TouchableOpacity
Dimensions,
} from 'react-native'
class Home extends Component {
constructor(props) {
super(props);
}
static navigationOptions = ({ navigation }) => ({
title: ''
})
render() {
return (
<Footer />
);
}
}
export default Home
But when I click "About" text, it returns
TypeError: undefined is not an object (evaluating
this.props.navigation.navigate) in react native
Please help. Thanks before.
You need to pass navigation as a prop to the Footer
<Footer navigation={this.props.navigation} />
As the Footer will be unaware of the navigation stack
send Home props to footer as below
<Footer {...this.props} />
Related
When I run my app I get the error: 'The component for route 'Camera' must be a react component'. I do not know what this means:
Here is my App.js:
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { createAppContainer } from 'react-navigation';
import {createStackNavigator} from 'react-navigation-stack';
import Home from './screens/Home';
import Camera from './screens/Camera'
const MainNavigator = createStackNavigator(
{
Home: {screen: Home},
Camera: { screen: Camera}
},
{
defaultNavigationOptions: {
headerTintColor: '#fff',
headerStyle: {
backgroundColor: '#b83227'
},
headerTitleStyle: {
color: '#fff'
}
}
}
);
Here is my home:
import React from 'react';
import { StyleSheet, Text, View, Image, Button } from 'react-native';
import Camera from './Camera'
export default class Home extends React.Component{
static navigationOptions = {
title: "PhotoClicker"
}
render(){
let photo = this.props.navigation.getParam("Photo", "empty")
const { navigate } = this.props.navigation;
return (
<View style={styles.container}>
<Image
resizeMode="center"
style = {styles.imageHolder}
source={
photo === "empty" ? require("../assets/viking.png") : photo
}
/>
<Button
title="Take Photo"
style={styles.button}
onPress={()=>{
this.props.navigation.navigate(Camera)
}}
/>
</View>
);
}
}
Here is Camera:
import React from 'react';
import { StyleSheet, Text, View, Image, Button } from 'react-native';
export default class Camera extends React.Component{
render(){
const { navigate } = this.props.navigation;
return (
<View style={styles.container}>
<Text>Camera Screen</Text>
</View>
);
}
}
It should just be a button that leads from home to Camera, but all I get is the above error. I have tried to change the imports but I just keep getting the same error. Could there be something wrong with my setup, I feel I get many more errors not directly related to code with React-native than I would with Java for Android.
Since you are adding Camera Screen to createStackNavigator. You can navigate to that screen directly through navigation props. So remove below unnecessary import code from your Home Screen
import Camera from './Camera'
change your navigation action
this.props.navigation.navigate('Camera')
I am using react navigation as per the docs but trying to make my app a bit more modular. I placed the result of createStackNavigator into a separate component..
Navigator.js
import React, { Component } from 'react';
import {createAppContainer} from 'react-navigation';
import {createStackNavigator} from 'react-navigation-stack';
import Home from './views/Home.js';
import TestComponent from './views/TestComponent.js';
const MainNavigator = createStackNavigator({
Home: {screen: Home},
Test: {screen: TestComponent}
});
export default createAppContainer(MainNavigator);
..and importing this component into my App.js
App.js
import React, { Component } from 'react';
import { View } from 'react-native';
import Header from './Header.js';
import Navigator from './Navigator.js';
import FooterMenu from './FooterMenu.js';
class App extends Component {
render() {
return (
<View>
<Header />
<Navigator />
<FooterMenu />
</View>
);
}
}
export default App;
My index.js is as follows:
import { AppRegistry } from 'react-native';
import App from './components/App';
import {name as appName} from './app.json';
AppRegistry.registerComponent(appName, () => App);
Im finding that my <Header/> and <FooterMenu/> components are rendering but the <Navigator/> component is not.
I found that if I replace the top-level <View> component with a React fragment, it does render.
render() {
return (
<>
<Header />
<Navigator />
<FooterMenu />
</>
);
}
Although this syntax breaks my editor's (sublime) syntax highlighting. Though if I change the fragment to <React.Fragment> React native throws an exception.
My questions are:
Why does <Navigator/> not render if I wrap it in a <View> component?
Why do I get an error if I use <React.Fragment>?
If you want to create your own Navigator, here's how.
It is possible to take an existing Navigator and extend its behavior, using the following approach:
const MyStack = createStackNavigator({ ... });
class CustomNavigator extends React.Component {
static router = MyStack.router;
render() {
const { navigation } = this.props;
return <MyStack navigation={navigation} />;
}
}
Now it is possible to render additional things, observe the navigation prop, and override behavior of the router:
const MyStack = createStackNavigator({ ... });
class CustomNavigator extends React.Component {
static router = {
...MyStack.router,
getStateForAction: (action, lastState) => {
// check for custom actions and return a different navigation state.
return MyStack.router.getStateForAction(action, lastState);
},
};
componentDidUpdate(lastProps) {
// Navigation state has changed from lastProps.navigation.state to this.props.navigation.state
}
render() {
const { navigation } = this.props;
return (
<View>
<Header />
<MyStack navigation={navigation} />
<FooterMenu />
</View>
);
}
}
If you want to know more about this,
Can I achieve this layout?
sketch of layout:
the header part is shared across all tabs. it's part of the layout in this screen.
and each tab contains a scrollView.
btw, I have tried defining the tab navigator as a component and using that inside the render method, along with the static header component.
render() {
return (
<StaticHeaderComponent />
<MyTabNavigator />
)
}
that does not work. the tab navigator does not render at all.
Here is a simple working example:
MyTabNavigator.js
import React, { Component } from 'react'
import { View, Text, ScrollView } from 'react-native'
import { TabNavigator } from 'react-navigation'
class FirstTab extends Component {
render() {
return (
<ScrollView>
<Text>first tab</Text>
</ScrollView>
)
}
}
class SecondTab extends Component {
render() {
return (
<ScrollView>
<Text>second tab</Text>
</ScrollView>
)
}
}
const MyNavigator = TabNavigator({
first: { screen: FirstTab },
second: { screen: SecondTab }
},
{
tabBarPosition: 'top'
})
export default MyNavigator
App.js
import React, { Component } from 'react'
import { View } from 'react-native'
import MyTabNavigator from './MyTabNavigator'
export default class App extends Component {
render() {
return (
<View style={{flex: 1}}>
<View // place your StaticHeaderComponent here
style={{height: 100, backgroundColor: 'green'}}
/>
<MyTabNavigator/>
</View>
)
}
}
For react-navigation 3.+ the Common mistakes section of the documentation comes in handy. You can find the documentation and the example here.
Specifically, you need to expose the static router and pass navigation as a prop. You can further customise the tab styles as required.
const TabbyNavigator = createMaterialTopTabNavigator({
Tab: TabScreen,
AnotherTab: AnotherTabScreen
});
class SomeScreen extends React.Component {
static router = TabbyNavigator.router;
render() {
return (
<TabbyNavigator navigation={this.props.navigation} />
);
}
}
I have a HomePage.js which contains About Us button, and when I click on that button I want to show AboutUs.js. The HomePage.js is displayed correctly, however, when I click on the button it gives me the following error: this.props.onPress is not a function. (In 'this.props.onPress(e)', 'this.props.onPress' is an instance of Object)
I have App.js
import React, { Component } from 'react';
import { StackNavigator } from 'react-navigation';
import HomePage from './HomePage';
import AboutUs from './AboutUs';
const App = StackNavigator({
HomePage: {
screen: HomePage,
navigationOptions: {
header: () => null
}
},
AboutUs: {
screen: AboutUs,
navigationOptions: {
header: () => null
}
}
});
export default App;
Then I have a reusable component Button.js:
import React from 'react';
import { Text, TouchableOpacity } from 'react-native';
const Button = ({ onPress, children }) => {
return (
<TouchableOpacity onPress={onPress}>
<Text>{children}</Text>
</TouchableOpacity>
);
};
export { Button };
HomePage.js which is rendering the Button component. When I press it I get the above mentioned error
import React, { Component } from 'react';
import { View, Text } from 'react-native';
import { Button } from './Button.js';
import AboutUs from './AboutUs';
class HomePage extends Component{
render() {
const { navigate } = this.props.navigation;
return(
<View>
<Button
onPress={() => navigate('AboutUs'), { name: 'About Us' }}
>About Us</Button>
</View>
)
}
}
export default HomePage;
AboutUs.js
import React, { Component } from 'react';
import { Text, View } from 'react-native';
class AboutUs extends Component {
render() {
return (
<View>
<Text>About us!</Text>
</View>
);
}
}
export default AboutUs;
This is not a valid function reference
onPress={() => navigate('AboutUs'), { name: 'About Us' }}
seems like you mixed up { name: 'About Us' } inside the function ref instead of as a prop to Button
I had a similar issue with the same error: "this.props.onPress is not a function" The mistake I made was using:
onPress={this.props.incrementCount()}
where the correct syntax is:
onPress={ () => this.props.incrementCount()}
the latter returns the results of the function.
for me it was i missed a curly brackets
onPress={() => {navigate('AboutUs'), { name: 'About Us' }}}
i am getting above mentioned error while running my code and have also searched about this error , i do understand the meaning of this error But i am not able to figure it out in my case.
Here is the code for index.android.js file :-
import React, { Component } from 'react';
import {
AppRegistry
} from 'react-native';
import TabNavigatoro from './src/pages/TabNavigatoro';
export default class ReactNewsfeedDemo extends Component {
render() {
return (
<TabNavigatoro/>
);
}
}
AppRegistry.registerComponent('ReactNewsfeedDemo', () => ReactNewsfeedDemo);
Code for TabNavigatoro.js :-
import React, { Component } from 'react';
import {
AppRegistry,
Image
} from 'react-native';
import { Actions, ActionConst } from 'react-native-router-flux';
import logoImg from '../images/logo.png';
import eyeImg from '../images/eye_black.png';
import homeView from './homeView';
import profileView from './profileView';
import TabNavigator from 'react-native-tab-navigator';
export default class TabNavigatoro extends Component {
constructor(props){
super(props);
this.state={selectedTab:'home'}
}
render() {
return (
<TabNavigator selectedTab = {this.state.selectedTab}>
<TabNavigator.Item
selected={this.state.selectedTab === 'home'}
title="Home"
renderIcon={() => <Image source={logoImg} />}
renderSelectedIcon={() => <Image source={logoImg} />}
onPress={() => this.setState({ selectedTab: 'home' })}>
{homeView}
</TabNavigator.Item>
<TabNavigator.Item
selected={this.state.selectedTab === 'profile'}
title="Profile"
renderIcon={() => <Image source={eyeImg} />}
renderSelectedIcon={() => <Image source={eyeImg} />}
onPress={() => this.setState({ selectedTab: 'profile' })}>
{profileView}
</TabNavigator.Item>
</TabNavigator>
);
}
}
Here is homeView.js code :-
import React, { Component } from 'react';
import {
StyleSheet,
Text,
View,
Image,
TouchableOpacity,
TextInput,
} from 'react-native';
export default class homeView extends Component {
render() {
return (
<View style={styles.container} >
<Text style = {styles.description}>
This is Home View , Please click to confirm.
</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container : {
flex:1,
alignSelf : 'stretch',
justifyContent:'center',
},
description : {
fontSize:16,
color: '#ffffff',
textAlign:'center',
},
});
I found one link with same error but it was not answered :-
https://github.com/expo/react-native-tab-navigator/issues/130
please let me know what actually causing problem whey it's no picking {homeView} and {profileView} pages, why it's coming null ?
Appreciate!!!