ReactNative navigation - react-native

I'm having a great deal of trouble implementing a navigationsystem for my ReactNative app. Here's the index.js:
class Test extends Component {
render() {
const routes = [
{title: 'LoginScreen', index: 0},
{title: 'RegisterScreen', index: 1},
];
return (
<Navigator
initialRoute={routes[0]}
initialRouteStack={routes}
renderScene={(route, navigator) =>
<TouchableHighlight onPress={() => {
navigator.push(routes[1]);
}}>
<Text>Hello {route.title}!</Text>
</TouchableHighlight>
}
style={{padding: 100}}
/>
)
}
}
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
} else {
}
});
At the moment I have simply written a navigation straight off the docs. But I would want it to transition to another screen inside the if statements when checking for a Firebase user. So transitioning to one scene if a user exists and another scene if not.
I find the documentation of this very poor, so I can't even build a basic idea of how to modify this method of transitioning (seems to be endless ways of doing it, sigh..) into working to my situation.

You can definitely use the below example, It hops onto screens by 2 if he found user or hops onto screens by 1.
Assuming user already present
1. index.android.js
import React,{Component} from 'react';
import{
AppRegistry,
StyleSheet,
Text,
ScrollView,
Navigator,
View,
} from 'react-native';
import Navigation from './navigation'
export default class Example extends Component{
constructor(){
super();
this.state={
username: 'ABC',
}
}
render() {
var nextIndex
return (
<Navigator
initialRoute={{ title: 'My Initial Scene', index: 0 }}
renderScene={(route, navigator) =>
<Navigation
title={route.title}
onForward={() => {
if(this.state.username)
nextIndex = route.index + 2 ;
else
nextIndex = route.index + 1 ;
navigator.push({
title: 'Scene ' + nextIndex,
index: nextIndex,
});
}}
onBack={() => {
if (route.index > 0) {
navigator.pop();
}
}}
/>
}
/>
);
}
}
AppRegistry.registerComponent('Example', () => Example);
2. navigation.js
import React,{Component} from 'react';
import{
StyleSheet,
Text,
Navigator,
TouchableHighlight,
View,
} from 'react-native';
export default class Navigation extends Component{
constructor(props) {
super(props)
}
render() {
return (
<View>
<Text>Current Scene: {this.props.title}</Text>
<TouchableHighlight onPress={this.props.onForward}>
<Text>Tap me to load the next scene</Text>
</TouchableHighlight>
<TouchableHighlight onPress={this.props.onBack}>
<Text>Tap me to go back</Text>
</TouchableHighlight>
</View>
)
}
}
This is the working example for RN 0.40.0

Related

react native - Callback in component with 'prop-types'

I have Gallery component like:
import React from 'react';
... Some import
import PropTypes from 'prop-types';
import {
TouchableOpacity,
Image,
FlatList
} from 'react-native';
export default class Gallery extends React.Component {
constructor(props) {
super(props);
this.state = {
selected: 0,
data: this.props.data
}
}
render() {
return (
<FlatList
showsHorizontalScrollIndicator={false}
horizontal={true}
data={this.state.data}
keyExtractor={(item, index) => item.id}
renderItem={({item, index}) =>
<TouchableOpacity
disabled={this.props.overlay && this.state.selected==index}
// onPress={this.props.actionOnPress}
onPress={()=>{
if(this.props.overlay) {
this.setState({
selected: index,
data: [...this.props.data]
});
}
this.props.actionOnPress;
}}>
<Image
source={{uri: item.imageUrl}}
style={[gallery.galleryItem, this.props.overlay && this.state.selected!=index ?gallery.overlay : null,
index==0 ? gallery.firstGalleryItem : ( index+1 == Object.keys(this.props.data).length ? gallery.lastGalleryItem : null )]}/>
</TouchableOpacity>
}
/>
);
}
}
Gallery.propTypes = {
data: PropTypes.array,
actionOnPress: PropTypes.func,
overlay: PropTypes.bool
}
and I have used Gallery component like
import React from 'react';
import common from '../../assets/styles/common/common'
import galleryPreview from '../../assets/styles/common/galleryPreview'
import icons from '../../assets/styles/common/icon'
import Icons from '../../config/ConstantIcon'
import Gallery from '../common/Gallery'
import {
View,
Text,
StatusBar,
TouchableOpacity,
Image
} from 'react-native';
const data = [ List item here];
export default class GalleryPreview extends React.Component {
render() {
return (
<View>
... Some code here
<Gallery data={data} overlay={true}/>
... Some code here
</View>
);
}
}
How to use callback from Gallery component like <Gallery data={data} actionOnPress={({item, index})=> console.log(item)}/>. item and index will be get from Gallery component.
I have used onPress={this.props.actionOnPress} but I can not insert
if(this.props.overlay) {
this.setState({
selected: index,
data: [...this.props.data]
});
}
and not callback param item and index
can you guys help me?
thanks,
Just call the function with the arguments:
onPress={() => {
...
this.props.actionOnPress({ item, index });
}}

How to setState without using .bind(this) in react-native?

I have no idea How to set state.
Below is my code...
import React from 'react';
import { StyleSheet, Text, View, TouchableHighlight, AsyncStorage, ListView } from 'react-native';
export default class App extends React.Component {
constructor(){
super();
this.state = {
myLeader: 'Joe',
};
}
setMyLeader(name){
this.setState({
myLeader: name
});
}
render() {
return (
<View>
<TouchableHighlight
style={{padding: 30}}
onPress={this.setState(myLeader: 'xxx')}
>
<Text>foo</Text>
</TouchableHighlight>
</View>
);
}
}
error message is this. 'Can't find variable: myLeader'
How to fix this problem?
Inside your onPress function you can:
a) directly set the state
onPress={() => this.setState({ myLeader: 'xxx' })}
b) call your setLeader function
onPress={() => this.setMyLeader('xxx')}

NavigatorIOS problems

Hi I'm having some trouble using the NavigatorIOS in my app, it gives me the error:'undefined is not an object(evaluating 'this.props.navigator.push').
I tried to see some examples but I can't see the error, can someone help me?
Here is the code:
import React, { Component, PropTypes } from 'react';
import Dimensions from 'Dimensions';
import Menu from './Menu'
import {
AppRegistry,
StyleSheet,
Image,
TouchableHighlight,
NavigatorIOS,
FadeInView,
Text,
View
} from 'react-native';
class Home extends React.Component {
constructor(props, context) {
super(props, context);
this.onForward = this.onForward.bind(this);
}
onForward(Menu){
this.props.navigator.push({
component: Menu,
title: "Menu",
navigationBarHidden: true,
});
}
render() {
return (
<View style={styles.container}>
<Image
style={styles.img}
source={require('./img/scrittaNera.png')}
onLoadStart={(e) => this.setState({loading: true})}
/>
<TouchableHighlight style={styles.button} onPress={() => this.onForward()}>
<Text style={styles.buttonText}>Get Inspired</Text>
</TouchableHighlight>
</View>
);
}
}
Thanks
You need to bind the function to your Component in this case this can be done as follows:
<TouchableHighlight
style={styles.button}
onPress=this.onForward.bind(this)>
....
</TouchableHighlight>
Also you need to make sure your main component is wrapped inside a <NavigatorIOS> component. Such as:
import React, { Component, PropTypes } from 'react';
import { NavigatorIOS, Text } from 'react-native';
export default class NavigatorIOSApp extends Component {
render() {
return (
<NavigatorIOS
initialRoute={{
component: MyScene,
title: 'My Initial Scene',
}}
style={{flex: 1}}
/>
);
}
}

NavigatorIOS not rendering initialroute

I pretty much copied and pasted the demo code from Facebook, but the initialRoute component does not render. Answers like setting flex:1 as suggested by similar questions didn't work for me. Any tips?
import React, { Component } from 'react';
import {
StyleSheet,
NavigatorIOS,
StatusBar,
AppRegistry,
View,
Text,
TouchableHighlight,
} from 'react-native';
import NativeThing from './components/ReactNative';
export default class ListsList extends Component {
render() {
return (
<NavigatorIOS
initialRoute={{
component: MyScene,
title: 'My Initial Scene',
}}
style={{flex: 1}}
/>
);
}
}
class MyScene extends Component {
_onForward = () => {
this.props.navigator.push({
title: 'Scene ' + nextIndex,
});
}
render() {
return (
<View>
<Text>Current Scene: { this.props.title }</Text>
<TouchableHighlight onPress={this._onForward}>
<Text>Tap me to load the next scene</Text>
</TouchableHighlight>
</View>
)
}
}
var styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#F5FCFF',
}
});
AppRegistry.registerComponent('ListsList', () => ListsList);
The navigation bar by default overlaps the content of MyScene component. This is the default behaviour of the NavigatorIOS with a translucent
navigation bar.
So you have two options:
Add style paddingTop: 64 to the View of MyScene.
Add property translucent={ false } to the NavigatorIOS

React Native Navigator : Expected a component class, got [object Object]

the error which is shown in the title gets displayed when I try to load a new Component through the Navigator component.
My View with the Navigator component looks as following:
render(){
return(
<Navigator
initialRoute={{name: 'Feed', component: Feed}}
renderScene={(route, navigator) => {
if(route.component){
return React.createElement(route.component, {navigator, ...this.props})
}
}
}
/>
)
}
}
The initialRoute renders the correct View perfectly.
The child Component Feed that gets rendered contains a list of Buttons which update the Navigator and cause it to render a new component as following:
updateRoute(route){
this.props.globalNavigator(route)
this.props.navigator.push({
name: route.displayLabel,
component: route.label
})
}
render(){
return(
<View style={styles.bottomNavSection}>
{
this.state.navItems.map((n, idx) => {
return(
<TouchableHighlight
key={idx}
style={this.itemStyle(n.label, 'button')}
onPress={this.updateRoute.bind(this, n)}
>
<Text
style={this.itemStyle(n.label, 'text')}
>
{n.displayLabel}
</Text>
</TouchableHighlight>
)
})
}
</View>
)
}
Note that the function updateRoute(route) receives the name of the new component as following: onPress={this.updateRoute.bind(this, n)}. Where n equals to {displayLabel: 'Start', label: 'Feed', icon: ''}, for example.
Edit
Content of my Profil.js Component:
import React, { Component } from 'react'
import ReactNative from 'react-native'
import API from '../lib/api'
import BottomNavigation from '../components/BottomNavigation'
const {
ScrollView,
View,
Text,
TouchableHighlight,
StyleSheet,
} = ReactNative
import { connect } from 'react-redux'
class Profil extends Component {
constructor(props){
super(props)
}
render(){
return(
<View style={styles.scene}>
<ScrollView style={styles.scrollSection}>
<Text>Profil</Text>
</ScrollView>
<BottomNavigation {...this.props} />
</View>
)
}
}
const styles = StyleSheet.create({
scene: {
backgroundColor: '#0f0f0f',
flex: 1,
paddingTop: 20
},
scrollSection: {
flex: .8
}
})
function mapStateToProps(state){
return {
globalRoute: state.setGlobalNavigator.route
}
}
export default connect(mapStateToProps)(Profil)
The issue was that onPress={this.updateRoute.bind(this, n)} wasn't containing the proper component reference but instead was containing the component name as String.
Fixed it by altering the function :
updateRoute(route){
this.props.globalNavigator(route)
this.props.navigator.push({
name: route.displayLabel,
component: route.component
})
}
and enhancing the state with the component reference and importing the component in the beginning of the document.
this.state = {
navItems: [
{displayLabel: 'Start', label: 'Feed', icon: start, component: Feed},
]
}
I think you forget to export your component.