React-Native Navigator Android Error - react-native

Native app development
This is what I tried
File: index.android.js
/**
* Sample React Native App
* https://github.com/facebook/react-native
* #flow
*/
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Navigator,
TouchableHighlight,
Text,
View
} from 'react-native';
var Loader = require('./app/components/Loader');
var Login = require('./app/components/Login');
export default class Demo extends Component {
constructor(props) {
super(props);
}
render() {
return (
<Navigator>
initialRoute = {{
id:'Loader',
}}
renderScene = {(route, navigator) => {
_navigator = navigator;
switch (route.id){
case 'Loader':
return (<Loader navigator={navigator} route={route} title="Loader"/>);
case 'Login':
return (<Login navigator={navigator} route={route} title="Login"/>);
}
}
}
</Navigator>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
AppRegistry.registerComponent('Demo', () => Demo);
My Loader Component :
import React, { Component } from 'react';
import {
StyleSheet,
Text,
View,
Image
} from 'react-native'
class Loader extends Component{
constructor(props) {
super(props);
this.state = {
id: 'Loader'
}
}
render(){
return(
<View style={styles.container}>
<Image source={require('../assets/img/ace-logo-white-01.png')} style={styles.logo}/>
<Text style={styles.loadingText}>Loading...</Text>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
backgroundColor: 'red'
},
logo: {
height: 30,
width: 50
},
loadingText: {
flex:1,
fontSize: 25,
paddingTop: 20,
color: 'white'
}
});
module.exports = Loader;
when I run the app I am getting error undefined is not a funtion(evaluating 'this.props.renderScene(route,this)')
I have tried this by watching some tutorials on Youtube but I can't find the answer to my problem.
What I want to do is when the app is launched the Loader component I made should load and then from loader component I redirect user to the Login componet but currently I am not able to load any component as it loads with the error I stated above.

Here is a sample code for you:
render() {
return (
<Navigator
initialRoute={{ id: 'Sample', name: 'Index' }}
renderScene={this.renderScene.bind(this)}
configureScene={(route, routeStack) => Navigator.SceneConfigs.FloatFromRight}
/>
); }
renderScene = (route, navigator) => {
if (route.id === 'Sample') {
return (
<Sample
navigator={navigator}
/>
);
}
}

You may have made some syntax mistakes with the code given by #JainZz. Try this
import Loader from './app/components/Loader'
export default class Demo extends Component {
constructor(props) {
super(props);
}
render() {
return (
<Navigator
initialRoute={{ id: 'Loader', name: 'Loader' }}
renderScene={this.renderScene.bind(this)}
configureScene={(route, routeStack) => Navigator.SceneConfigs.FloatFromRight}
/>
);
}
renderScene = (route, navigator) => {
if (route.id === 'Loader') {
return (
<Loader
navigator={navigator}
/>
);
}
}
}

Related

Force unmounting on screen change

I recently integrated React Redux and Redux Thunk into my application in the hope that it would better allow me to manage state across screens.
However, using my navigation library (react native router flux), when ever I navigate between screens I get warnings of trying to set state across unmounted components and I am not sure what I would even need to unmount in componentWillUnmount as no calls should happen after a screen navigation.
My question then is, how can I force unmount everything on componentWillUnmount? Is there something built into React Native that I should use? Or, in my navigation library?
import React, { Component } from 'react';
import { View, Text, StyleSheet } from 'react-native';
import * as Font from 'expo-font'
class CustomText extends Component {
async componentDidMount() {
await Font.loadAsync({
'varelaround-regular': require('../../../assets/fonts/varelaround-regular.ttf'),
'opensans-regular': require('../../../assets/fonts/opensans-regular.ttf'),
'opensans-bold': require('../../../assets/fonts/opensans-bold.ttf'),
});
this.setState({ fontLoaded: true });
}
state = {
fontLoaded: false,
};
setFontType = type => {
switch (type) {
case 'header':
return 'varelaround-regular';
case 'bold':
return 'opensans-bold';
default:
return 'opensans-regular';
}
};
render() {
const font = this.setFontType(this.props.type ? this.props.type : 'normal');
const style = [{ fontFamily: font }, this.props.style || {}];
const allProps = Object.assign({}, this.props, { style: style });
return (
<View>
{
this.state.fontLoaded ? (
<Text {...allProps}>{this.props.children}</Text>
) : <Text></Text>
}
</View>
);
}
}
export default CustomText;
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center'
}
});
And one of my screens:
import React from "react";
import { ActivityIndicator, Image, StyleSheet, View } from "react-native";
import { Actions } from "react-native-router-flux";
import { connect } from "react-redux";
import * as profile from "../actions/profile";
import {
CustomText
} from "../components/common/";
class Home extends React.Component {
componentDidMount() {
this.props.loadProfile();
}
renderScreen() {
return (
<View style={{ flex: 1 }}>
<View style={{ flex: 0.3 }}>
<CustomText type="header" style={styles.headerTextStyle} onPress={() => Actions.home()}>
Hello {this.props.name}!
</CustomText>
</View>
</View>
);
}
renderWaiting() {
return (
<GradientBackground type="purple">
<View
style={{ flex: 1, justifyContent: "center", alignItems: "center" }}
>
<ActivityIndicator size="large" color="#FFF" />
</View>
</GradientBackground>
);
}
render() {
return (
<View style={{ flex: 1 }}>
{this.props.isLoading == true
? this.renderWaiting()
: this.renderScreen()}
</View>
);
}
}
function mapStateToProps(state) {
return {
name: state.profile.profile.friendly_name,
isLoading: state.profile.isLoading,
error: state.profile.error
};
}
function mapDispatchToProps(dispatch) {
return {
loadProfile: () => dispatch(profile.loadProfile())
};
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(Home);
const styles = StyleSheet.create({
headerTextStyle: {
color: "#FFFFFF",
fontSize: 40,
textAlign: "center",
marginVertical: 50
},
basicViewStyle: {
flex: 1
}
});

Cant find the variable React-native

native . I made the status component and router.js file .The emulator giving me error Cant find varible i do not know what is the problem but im getting this error in emulator .
here is my code
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View
} from 'react-native';
import StatusComponent from './component/StatusComponent';
import HeaderComponent from './component/headerComponent';
import Router from './component/Router';
import MainPage from './component/MainPage';
export default class Point extends Component {
render() {
return (
<View style={{flex: 1,backgroundColor: 'white'}}>
<StatusComponent/>
<HeaderComponent/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
} );
AppRegistry.registerComponent('Point', () => Point);
and here is my status component
import React,{ Component } from 'react';
import {
Text,
View,
StyleSheet
} from 'react-native';
export class StatusComponent extends Component{
render()
{
return(
<View style={styles.Bar}>
</View>
)
};
}
export default StatusComponent;
const styles=StyleSheet.create({
Bar:{
backgroundColor: 'white',
height: 20
}
})
here is code for Router.Js this file cousing the issue
import React, { Component } from 'react'
import {
StyleSheet,
Text,
Navigator,
TouchableOpacity
} from 'react-native'
import MainPage from './MainPage'
import Sports from './Sports'
export default class Router extends Component {
constructor(){
super()
}
render() {
return (
<Navigator
initialRoute = {{ name: 'MainPage', title: 'MainPage' }}
renderScene = { this.renderScene }
navigationBar = {
<Navigator.NavigationBar
style = { styles.navigationBar }
routeMapper = { NavigationBarRouteMapper } />
}
/>
);
}
renderScene(route, navigator) {
if(route.name == 'MainPage') {
return (
<MainPage
navigator = {navigator}
{...route.passProps}
/>
)
}
if(route.name == 'Sports') {
return (
<Sports
navigator = {navigator}
{...route.passProps}
/>
)
}
}
}
var NavigationBarRouteMapper = {
LeftButton(route, navigator, index, navState) {
if(index > 0) {
return (
<TouchableOpacity
onPress = {() => { if (index > 0) { navigator.pop() } }}>
<Text style={ styles.leftButton }>
Back
</Text>
</TouchableOpacity>
)
}
else { return null }
},
RightButton(route, navigator, index, navState) {
if (route.openMenu) return (
<TouchableOpacity
onPress = { () => route.openMenu() }>
<Text style = { styles.rightButton }>
{ route.rightText || 'Menu' }
</Text>
</TouchableOpacity>
)
},
Title(route, navigator, index, navState) {
return (
<Text style = { styles.title }>
{route.title}
</Text>
)
}
};
const styles = StyleSheet.create({
navigationBar: {
backgroundColor: 'blue',
},
leftButton: {
color: '#ffffff',
margin: 10,
fontSize: 17,
},
title: {
paddingVertical: 10,
color: '#ffffff',
justifyContent: 'center',
fontSize: 18
},
rightButton: {
color: 'white',
margin: 10,
fontSize: 16
}
})
In the StatusComponent file, you have export in front of the class StatusComponent extends Component. You should remove that export and leave the export default StatusComponent; at the bottom.
If after that, it still doesn't work then check the absolute path you are using to import the StatusComponent. Make sure it's correct
there is mistake in statusComponent file and thats very stupid mistake

React Native `alignItems: 'flex-end'` hides content in TabBarIOS component

This question is similar to this one however I have different requirements. I have a <TabBarIOS> component that renders a <Camera> from react-native-camera. I need to place a button to take a picture at the bottom of the <Camera> component but above the <TabBarIOS> component.
index.ios.js
import React, { Component } from 'react';
import {
AppRegistry,
TabBarIOS,
ScrollView,
StyleSheet,
Text,
View
} from 'react-native';
import CameraTab from './views/CameraTab.ios.js';
import FilesTab from './views/FilesTab.ios.js';
import Icon from 'react-native-vector-icons/MaterialIcons';
export default class MyApp extends Component {
constructor(props) {
super(props);
this.state = {
selectedTab: 'cameraTab'
};
};
_renderContent() {
switch (this.state.selectedTab) {
case "filesTab":
return <FilesTab style={styles.tabContent}></FilesTab>;
case "cameraTab":
return <CameraTab style={styles.tabContent}></CameraTab>;
case "settingsTab":
return <View style={styles.tabContent}></View>;
default:
return <View style={styles.tabContent}></View>;
}
};
render() {
return (
<TabBarIOS
tintColor="#3498db"
barTintColor="#ecf0f1">
<Icon.TabBarItemIOS
title="Files"
iconName="folder"
selected={this.state.selectedTab === "filesTab"}
onPress={() => {
this.setState({
selectedTab: "filesTab",
});
}}>
{this._renderContent()}
</Icon.TabBarItemIOS>
<Icon.TabBarItemIOS
title="Camera"
iconName="photo-camera"
badge={this.state.notifCount > 0 ? this.state.notifCount : undefined}
selected={this.state.selectedTab === "cameraTab"}
onPress={() => {
this.setState({
selectedTab: "cameraTab",
notifCount: this.state.notifCount + 1,
});
}}>
{this._renderContent()}
</Icon.TabBarItemIOS>
<Icon.TabBarItemIOS
title="Settings"
iconName="settings"
selected={this.state.selectedTab === 'settingsTab'}
onPress={() => {
this.setState({
selectedTab: "settingsTab",
presses: this.state.presses + 1
});
}}>
{this._renderContent()}
</Icon.TabBarItemIOS>
</TabBarIOS>
);
}
}
var styles = StyleSheet.create({
tabContent: {},
});
AppRegistry.registerComponent('myapp', () => myApp);
CameraTab.ios.js
import React, { Component } from 'react';
import {
Dimensions,
StyleSheet,
Text,
View
} from 'react-native';
import Camera from 'react-native-camera';
export default class CameraTab extends Component {
constructor(props) {
super(props);
this.state = {};
};
render() {
return (
<Camera
ref={(cam) => {
this.camera = cam;
}}
style={styles.preview}
aspect={Camera.constants.Aspect.fill}>
</Camera>
);
}
takePicture() {
this.camera.capture()
.then((data) => console.log(data))
.catch(err => console.error(err));
}
}
var styles = StyleSheet.create({
preview: {
flex: 1,
flexDirection: 'row',
alignItems: 'flex-end',
height: Dimensions.get('window').height,
width: Dimensions.get('window').width
},
capture: {
backgroundColor: '#fff',
borderRadius: 5,
color: '#000',
height: 20
}
});
module.exports = CameraTab;
I've tried various things but the capture button is always hidden when alignItems: 'flex-end' is in the container component's style.
It should look something like this:
Edit: I've discovered this issue that describes a workaround (placing the button component outside of the camera component). According to RN's docs on Height and Width it seems that this solution will work for all screen dimensions. However this doesn't work for me because I want a Subview with icons inside the camera.
OK, finally fixed it. I think the problem had to do with the height and width in the preview style. Working code:
import React, { Component } from 'react';
import {
Dimensions,
StyleSheet,
Text,
TouchableHighlight,
View
} from 'react-native';
import Camera from 'react-native-camera';
import Icon from 'react-native-vector-icons/Ionicons';
export default class CameraTab extends Component {
constructor(props) {
super(props);
this.state = {};
};
render() {
return (
<View style={styles.container}>
<Camera
ref={(cam) => {
this._camera = cam;
}}
style={styles.preview}
aspect={Camera.constants.Aspect.fill}
captureTarget={Camera.constants.CaptureTarget.disk}>
<TouchableHighlight
style={styles.cameraButton}
onPress={this._takePicture.bind(this)}>
<Icon name="ios-qr-scanner" size={55} color="#95a5a6" />
</TouchableHighlight>
</Camera>
</View>
);
}
_takePicture() {
this._camera.capture()
.then((data) => {
console.log(data)
})
.catch((err) => {
console.error(err)
});
}
}
var styles = StyleSheet.create({
cameraButton: {
flex: 0,
flexDirection: 'row',
marginBottom: 60,
},
container: {
flex: 1,
},
preview: {
flex: 1,
flexDirection: 'row',
alignItems: 'flex-end',
justifyContent: 'space-around'
},
});
module.exports = CameraTab;

How to pass data from one screen to other screen in React Native

1. index.android.js
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
TextInput,
View
} from 'react-native';
import Button from 'react-native-button';
class AwesomeProject extends Component {
constructor(props){
super(props)
this.state = {
username: '',
email: '',
address: '',
mobileNumber: ''
}
render() {
return (
<View style={styles.container}>
<TextInput
ref={component => this.txt_input_name = component}
style={styles.textInputStyle}
placeholder="Enter Name"
returnKeyLabel = {"next"}
onChangeText={(text) => this.setState({username:text})}
/>
<Button style={styles.buttonStyle}>
Submit
</Button>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
buttonStyle: {
alignSelf: 'center',
textAlign: 'center',
color: '#FFFFFF',
fontSize:18,
marginTop:20,
marginBottom:20,
padding:5,
borderRadius:5,
borderWidth:2,
width:100,
alignItems: 'center',
backgroundColor:'#4285F4',
borderColor:'#000000'
}
});
AppRegistry.registerComponent('AwesomeProject', () => AwesomeProject);
You need to pass the props to another page using navigator
this.props.navigator.push({
name: 'Home',
passProps: {
name: property
}
})
i took this from this link https://medium.com/#dabit3/react-native-navigator-navigating-like-a-pro-in-react-native-3cb1b6dc1e30#.6yrqn523n
Initially
import {Navigator}
Define Navigator inside the
render
function of
index.android.js
like this
render() {
return (
<Navigator
initialRoute={{id: 'HomePage', name: 'Index'}}
renderScene={this.renderScene.bind(this)}
configureScene={(route) => {
if (route.sceneConfig) {
return route.sceneConfig;
}
return Navigator.SceneConfigs.FloatFromRight;
}} />
);
}
Then define the
renderscene function
like this
renderScene(route, navigator) {
var routeId = route.id;
if (routeId === 'HomePage') {
return (
<HomePage
navigator={navigator} />
);
}
if (routeId === 'DetailPage') {
return (
<DetailPage
navigator={navigator}
{...route.passProps}
/>
);
}
}
Specify the property
{...route.passProps}
for passing values to a screen. Here I have given it inside the DetailPage
Then you can use
passProps
for calling the next page. In my case
DetailPage
this.props.navigator.push({
id: 'DetailPage',
name: 'DetailPage',
passProps: {
name:value
}
});

Issue on loading component with TabBarIOS through Navigator

I've been trying to load up a component through RenderScene function under Navigator. If the route doesn't contain any corresponding object based on the route.object I would fire up the navigator to return the view with the tabBarIOS, the code on the second snippet is how the TabView looks.
render: function() {
var initialRoute = {login: true};
return (
<Navigator
ref="navigator"
style={styles.container}
configureScene={(route) => {
if(Platform.OS === 'android') {
return Navigator.SceneConfigs.FloatFromBottomAndroid;
}
//
else {
return Navigator.SceneConfigs.FloatFromBottom;
}
}}
initialRoute={initialRoute}
renderScene={this.renderScene}
navigationBar={
<Navigator.NavigationBar
routeMapper={NavigationBarRouteMapper}
style={styles.navBar}
/>
}
/>
);
},
renderScene: function(route, navigator) {
if(route.login) {
return (
<LoginScreen
navigator={navigator}
onLogin={route.callback}
/>
);
}
return (
<HomeTab navigator={navigator}/>
);
}
The component with the tabs and supposedly the homepage after logging in is this
import React, { Component } from 'react';
import {
AppRegistry,
TabBarIOS,
StyleSheet
} from 'react-native';
var Welcome = require('./welcome.ios');
var More = require('./more.ios');
export default class TabBarIOSSpike extends Component {
constructor(props) {
super(props);
this.state = {
selectedTab: 'welcome'
};
}
render() {
return (
<TabBarIOS selectedTab={this.state.selectedTab}>
<TabBarIOS.Item
selected={this.state.selectedTab === 'welcome'}
icon={{uri:'featured'}}
onPress={() => {
this.setState({
selectedTab: 'welcome',
});
}}>
<Welcome/>
</TabBarIOS.Item>
<TabBarIOS.Item
selected={this.state.selectedTab === 'more'}
icon={{uri:'contacts'}}
onPress={() => {
this.setState({
selectedTab: 'more',
});
}}>
<More/>
</TabBarIOS.Item>
</TabBarIOS>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
I've been getting the weird error below. By the way, I've tested loading the hometab as the homepage and it works fine, only in this case if its wired up from the navigator that it occurs.
Unhandled JS Exception: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object. Check the render method of `Navigator`.