React Native - Error navigating to child components - react-native

I am able to define the initial route(Home) and the app navigates to that route. Inside Home I am calling another component called BoxLists which is displayed as expected. The issue I am having is when calling another component called StationOne from inside BoxLists.
I am getting the following error: uncaught error: undefined is not an object (evaluating 'this.props.navigator.push'
So the question is: How can I navigate from BoxLists to StationOne?
Note: I am planning to navigate to additional components(StationOne, StationTwo, StationN+1) from BoxLists.
Here is the code although you can go to RNPlayground at https://rnplay.org/apps/rLB5HQ. Thanks!
class App extends React.Component {
navigatorRenderScene(route,navigator){
if (route.title == "Home")
{
return( <Home navigator={navigator} /> );
}
if (route.title == "StationOne")
{
return( <StationOne navigator={navigator} /> );
}
}
render() {
return (
<Navigator
initialRoute = {{ title: "Home" }}
renderScene = {this.navigatorRenderScene.bind(this)}
/>
);
}
}
class Home extends React.Component {
render() {
return (
<View style={{flex: 1}}>
<View style={styles.header}>
<Text style={styles.headerText}>AdView</Text>
</View>
<BoxLists author="station one" navigator={navigator} />
</View>
);
}
}
class BoxLists extends React.Component {
_goToStation(){
this.props.navigator.push({
title: 'StationOne'
});
}
render() {
return (
<View>
<Text>You are in BoxList. The passed prop is: {this.props.author}</Text>
<TouchableHighlight onPress={this._goToStation.bind(this)}>
<Text>Press here to go to StationOne</Text>
</TouchableHighlight>
</View>
);
}
}
class StationOne extends React.Component {
render() {
return (
<View style={{flex: 1}}>
<Text> This is station one </Text>
</View>
);
}
}

class Home extends React.Component {
render() {
return (
<View style={{flex: 1}}>
<View style={styles.header}>
<Text style={styles.headerText}>AdView</Text>
</View>
<BoxLists author="station one" navigator={this.props.navigator} />
</View>
);
}
}
You need to pass this.props.navigator for the BoxLists component as shown above

Related

How to change text in sibling component in react-native?

I have an 'OutputBox' component and want to change the text being displayed in the component when I click a button.
I've read about props and state and i can't seem to get them working the way i need them too. I just started react-native and have a heavy background c++. I thought i could just declare a variable, 'text' in the 'OutputBox' component and then call a 'setOutputBoxText' function and change the 'text' var. Getters and Setters paradigm. I just cant wrap my head around how to use props to 'pass args' to components and the such.
export default class HelloWorldApp extends Component {
render() {
return (
<View style={{ flex: 1, alignItems: "flex-end" }}>
<CustomButton
text="N"
onPress={() => {
OutputBox.setOutputBox('You head North');
alert("You head North");
}}
/>
<OutputBox></OutputBox>
</View>
);
}
}
class CustomButton extends Component {
render() {
const { text, onPress} = this.props;
return (
<TouchableOpacity style={styles.buttonStyle}
onPress={() => onPress()}
>
<Text style={styles.textStyle}>{text}</Text>
</TouchableOpacity>
);
}
}
class OutputBox extends Component {
constructor( props ) {
super( props );
var displayText = 'Hello Traveller';
}
setOutputBox( newText ){
displayText = newText;
}
render() {
return (
<View style={ styles.outputBox }>
<Text>{this.displayText}</Text>
</View>
);
}
}
I would expect to be able to do something similar to what i have, however i just keep getting a typeError: OutputBox.setOutputBox is not a function. I know this is the wrong paradigm for react-native. I can't seem to wrap my head around doing something like this with props and state.
UPDATE: I no longer get the error typeError: OutputBox.setOutputBox is not a function. Now, the OutputBox just doesn't display anything. How I do I get the <Text/> component of the OutputBox to change and display.
Here is the correct way to do it.
export default class HelloWorldApp extends Component {
constructor( props ) {
super( props );
this.state={
displayText : 'Hello Traveller',
}
}
render() {
return (
<View style={{ flex: 1, alignItems: "flex-end" }}>
<CustomButton
text="N"
onPress={() => {
this.setState({displayText:'You head North'})
}}
/>
<OutputBox text={this.state.displayText}/>
</View>
);
}
}
class CustomButton extends Component {
render() {
const { text, onPress} = this.props;
return (
<TouchableOpacity style={styles.buttonStyle}
onPress={() => onPress()}
>
<Text style={styles.textStyle}>{text}</Text>
</TouchableOpacity>
);
}
}
class OutputBox extends Component {
render() {
return (
<View style={ styles.outputBox }>
<Text>{this.props.displayText}</Text>
</View>
);
}
}
I just removed the OutputBox component and put a <Text> component in there. I realized i didn't need the OutputBox component, since it's only purpose was to display text. This is what i ended up with
export default class HelloWorldApp extends Component {
constructor( props ) {
super( props );
this.state={
displayText : 'Hello Traveller',
}
}
render() {
return (
<View style={{ flex: 1, alignItems: "flex-end" }}>
<CustomButton
text="N"
onPress={() => {
this.setState({displayText:'You head North'})
}}
/>
<Text>{this.state.displayText}</Text>
</View>
);
}
}
class CustomButton extends Component {
render() {
const { text, onPress} = this.props;
return (
<TouchableOpacity style={styles.buttonStyle}
onPress={() => onPress()}
>
<Text style={styles.textStyle}>{text}</Text>
</TouchableOpacity>
);
}
}

React Native can't find variable: navigate

I am doing stack navigation but I can't seem to be able to navigate I will get this error "Can't find variable: navigate" Here is the screenshot of my android emulator
This is my App class(main)
export default class App extends Component {
render() {
return (
<View style={styles.container}>
<Header/>
<AppNavigator/>
</View>
);
}
}
const AppNavigator = StackNavigator({
Cluster1: {
screen: Cluster1,
},
Play: {
screen: Play,
},
});
This is my Cluster1 class
export default class Cluster1 extends Component{
render(){
return(
<View>
<SectionList
renderSectionHeader={({ section }) => {
return (<SectionHeader section={section} />);
}}
sections={ClusterData}
keyExtractor={(item, index) => item.name}
>
</SectionList>
</View>
);
}
}
class SectionHeader extends Component {
render() {
return (
<View style={styles.header}>
<Text style={styles.headertext}>
{this.props.section.title}
</Text>
<TouchableOpacity onPress={() => { navigate("Play");}}>
<Text style ={styles.Play}>Play
</Text>
</TouchableOpacity>
</View>
);
}
}
navigation object only exist in the screen component. (not exist in the nested components). you can pass it into the nested component using props
export default class Cluster1 extends Component{
render(){
return(
<View>
<SectionList
renderSectionHeader={({ section }) => {
return (<SectionHeader navigation={this.props.navigation} section={section} />);
}}
sections={ClusterData}
keyExtractor={(item, index) => item.name}
>
</SectionList>
</View>
);
}
}
class SectionHeader extends Component {
render() {
return (
<View style={styles.header}>
<Text style={styles.headertext}>
{this.props.section.title}
</Text>
<TouchableOpacity onPress={() => { this.props.navigation.navigate("Play");}}>
<Text style ={styles.Play}>Play
</Text>
</TouchableOpacity>
</View>
);
}
}
Include on your SectionHeader the this.props.navigation something like this:
<SectionHeader navigation={this.props.navigation}/>
because the props.navigation are by default on your parent component
and on SectionHeader component you will access to navition like:
..
goToSignUp() {
this.props.navigation.navigate('SignUp');
}
..
For me also was confusing before. Cheers!
You can use this rather than navigate :
this.props.navigation.navigate('Play')
Hope this is helpful.

react-navigation not working, props is undefined

I am building a POC application in react-native and trying to implement react-navigation
import {StackNavigator, DrawerNavigator} from 'react-navigation';
export default class HomeScreen extends React.Component {
constructor(props) {
super(props)
this.clicked = this.clicked.bind(this)
}
static navigationOptions = {
drawerLabel: 'Home',
};
clicked = ()=> {
this.props.navigator.navigate('DrawerOpen'); // open drawer
}
render() {
// const {navigate} = this.props.navigation;
return (
<ScrollView>
<View style={styles.container}>
<View style={styles.header}>
<View style={{width: 50}}>
<TouchableHighlight onPress={()=> {
this.clicked("DrawerOpen")
}}>
<Image source={require('./img/hamburger_icon.png')}/>
</TouchableHighlight>
</View>
</View>
</View>
</ScrollView >
)
}
}
Now whenever I am clicking on touchable highlight, clicked function gets called and it shows error:
undefined is not an object (evaluating '_this.props.navigator.navigate')
clicked
You try it :)
import {StackNavigator, DrawerNavigator} from 'react-navigation';
export default class HomeScreen extends React.Component {
static navigationOptions = {
drawerLabel: 'Home',
};
clicked = () => {
this.props.navigation.navigate('DrawerOpen'); // open drawer
}
render() {
// const {navigate} = this.props.navigation;
return (
<ScrollView>
<View style={styles.container}>
<View style={styles.header}>
<View style={{width: 50}}>
<TouchableHighlight onPress={()=>
this.clicked()
}>
<Image source={require('./img/hamburger_icon.png')}/>
</TouchableHighlight>
</View>
</View>
</View>
</ScrollView >
)
}
}
Try this , May be this can help you, Inside the clicked
clicked = ()=> {
this.props.navigation.navigate('DrawerOpen');
}
This just happened to me. Only the top level components get the this.props.navigation.
Probably you have to call this component like this:
<HomeScreen navigation=this.props.navigation />

error: "undefined is not an object(evaluating 'this,props.navigation.navigate')" In React Native

Getting errors when navigating one page to other page in React Native.
error:
undefined is not an object(evaluating 'this,props.navigation.navigate')
code:
import { StackNavigator,NavigationActions } from "react-navigation";
const Navigation = StackNavigator({
Home : {
screen : Home
},
})
export default class App extends React.Component {
submit = () => {
this.props.navigation.navigate('Home');
}
render() {
return (
<View style={styles.container}>
<Text>Enter Log</Text>
<TextInput style={styles.input}
multiline={true}
underlineColorAndroid="transparent"
placeholder="Enter Log"
placeholderTextColor="#9a73ef"
autoCapitalize="none"
onChangeText={this.handlePassword} />
<TouchableOpacity style={styles.submitButton} onPress={() => submit } >
<Text style={styles.submitButtonText}> Submit </Text>
</TouchableOpacity>
</View>
);
}
}
}
You have to bind your method:
import { StackNavigator,NavigationActions } from "react-navigation";
const Navigation = StackNavigator({
Home : {
screen : Home
},
})
export default class App extends React.Component {
constructor(props) {
super(props);
this.submit = this.submit.bind(this);
}
render() {
return (
<View style={styles.container}>
<Text>Enter Log</Text>
<TextInput style={styles.input}
multiline={true}
underlineColorAndroid="transparent"
placeholder="Enter Log"
placeholderTextColor="#9a73ef"
autoCapitalize="none"
onChangeText={this.handlePassword} />
<TouchableOpacity style={styles.submitButton} onPress={this.submit} >
<Text style={styles.submitButtonText}> Submit </Text>
</TouchableOpacity>
</View>
);
}
submit() {
this.props.navigation.navigate('Home');
}
}
Explanation: Binding context when calling ES6 method. How to access object from within method called as callback?
Try changing your onPress value to this:
onPress={this.submit}
Also, I don't see you importing your Home component to where you assign it as a screen.

state property undefined in render function

In the render function on one of my views I am trying to have the opacity of a view be tied to a state property: this.state.infoOpacity.
This is turning an error "undefined is not an object (evaluating 'this.state.infoOpacity')"
Any guidance would be helpful.
export default class BookView extends Component
{
constructor(props) {
super(props);
this.state = {
hideInfo:false,
infoOpacity:0.80,
swiperWidth:Dimensions.get('window').width,
swiperHeight:Dimensions.get('window').height
};
}
render() {
pages.forEach(function(ranPage){
photoViews.push(
<View key={ranPage.letter} style={{width: Dimensions.get('window').width, height: Dimensions.get('window').height}}>
<View style={[styles.meow,{opacity: this.state.infoOpacity}]}>
<Text style={styles.text}>{ranPage.name}</Text>
<Text style={styles.text}>{ranPage.phonetic}</Text>
<Text style={styles.text2}>{ranPage.description}</Text>
</View>
</View>
)
});
return (
<View style={{flex:1}}>
<Swiper showsButtons={false} style={{backgroundColor:'#000'}} width={this.state.swiperWidth} height={this.state.swiperHeight}>
{photoViews}
</Swiper>
</View>
);
}
}
The context changed in your forEach function. Use an arrow function to fix your issue. So instead of
pages.forEach(function(ranPage){ ... });
write this
pages.forEach((ranPage) => { ... });