React native issue with navigation" - javascript

so I am really having a hard time with this navigation thing. I am not an expert in Js or react native, but since the person working on this app isn't in the company anymore, I am asked to make some tweaks here and there until a new person comes in but I am struggling with this navigation thing.
so I am using this to go to my two factor identification
any idea what does this navigate do anyway? how can I set it value? do it need to passe it somehow?
full code
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import {
View,
Text,
TouchableHighlight,
Image,
TextInput,
} from 'react-native'
import {requiredFields} from '../helpers/forms'
import BusyButton from '../Common/BusyButton'
import DismissKeyboard from '../Common/DismissKeyboard'
import {Colors} from '../styles'
import LoginStyles from './LogInStyles'
const loginStyles = LoginStyles.createStyles()
/* eslint-disable camelcase,space-before-function-paren */
export default class TwoFactor extends Component {
static propTypes = {
screenProps: PropTypes.object.isRequired,
navigation: PropTypes.object.isRequired,
}
state = {
verificationCode: '',
}
handleSubmit = () => {
try{
const {screenProps: {auth: {sendVerificationCode}}, navigation: {navigate}} = this.props
if (requiredFields(['verificationCode'], ['Verification Code'], this.state)) {
sendVerificationCode(this.state.verificationCode,this.state.user, navigate)
}
return false
}catch(e){
console.log(e)
}
}
render() {
const {screenProps: {auth: {isFetching}}} = this.props
return (
<DismissKeyboard style={loginStyles.pageWrapper}>
<View style={loginStyles.logoContainer}>
<Image
style={loginStyles.logo}
resizeMode="contain"
source={require('../../assets/images/logo-IH_blue_gold-small.png')}
/>
</View>
<View style={loginStyles.containerExpand}>
<Text style={loginStyles.h1}>ID Verification</Text>
<Text style={loginStyles.label}>
A verification code has been sent to the phone number on file. Please enter the code below.
</Text>
<TextInput
style={loginStyles.input}
placeholder="Verification Code"
placeholderTextColor={Colors.lightGray}
onChangeText={(verificationCode) => this.setState({verificationCode})}
keyboardType="number-pad"
/>
</View>
<View style={loginStyles.container}>
<View style={loginStyles.buttonContainer}>
<BusyButton
style={loginStyles.button}
underlayColor={Colors.buttonPrimaryBkgd}
isBusy={isFetching}
onPress={this.handleSubmit}
>
<Text style={loginStyles.buttonText}>Next</Text>
</BusyButton>
</View>
</View>
</DismissKeyboard>
)
}
}
ERROR
it's not spitting any error, but it is not taking me to the next screen.

Related

Object deconstruct all props with ...props

So if i have alot of different props for one component I wish i could do something like
const { ...props } = props;
instead of
const { prop1, prop2, prop3, ... } = props;
why isn't statement 1 valid? or am I doing the syntax wrong?
Edit: statement 1 is valid i see that was me being stupid now.
what im looking for is a programatic way to achieve statement 2 so i dont have to write out loads of props
option one is useful if you are using HOCs, for example in React native, if you are making animated components you can go:
import React from 'react';
import { Animated, Text} from 'react-native';
class ComponentToBeAnimated extends React.Component {
render() {
const {...other} = this.props;
return (
<Text {...other}>
hello world
</Text>
)
}
}
export const AnimatedText = Animated.createAnimatedComponent(ComponentToBeAnimated )
Then when you instantiate AnimatedText, you can apply styles as if you were instantiating Text
import React from 'react';
import { StyleSheet, View} from 'react-native';
import { AnimatedText } from './AnimatedText';
const styles = StyleSheet.create({
title: {
fontSize: 19,
fontWeight: 'bold',
},
});
export const Message = () => {
return (
<View>
<AnimatedText style={styles.title}/>
</View>
)
}
See you can apply all the Text props you want from the HOC

undefined is not an object (evaluating '_this.props.navigator.push')

I'm trying to navigate from Homescreen to another screen(Test).I have 'HomeScreen.js' below. Once I click on the register button, I get the above mentioned error.
I've been at this for a whole day, but can't seem to get a straight forward answer.
The error is on my 'Homescreen.js' (Attached screenshot error)
Screenshot
Error is pointing to: this.props.navigator.push under the _handleRegisterView function.
HomeScreen.js
import React from 'react';
import {
StyleSheet,
Text,
View,
AsyncStorage,
Component,
TouchableHighlight,
AppRegistry
} from 'react-native';
import Test from './Test';
import { StackNavigator } from 'react-navigation';
class HomeScreen extends React.Component {
static navigationOptions = {
title: 'SpeedHack',
};
_handleRegisterView = () => {
this.props.navigator.push({
title: 'Test',
component: Test,
backButtonTitle: 'Back'
})
//alert('Register button Pressed!.');
}
render() {
return (
<View style={styles.container}>
<TouchableHighlight onPress={this._handleRegisterView}>
<Text style={[styles.button, styles.blueButton]}>
Register
</Text></View>
);
}
}
Test.js (Doesn't really do anything interesting, loads an image)
import React from 'react';
import { Component, StyleSheet, Text, View, Image } from 'react-native';
class Test extends React.Component {
render() {
let pic = {
uri: 'https://upload.wikimedia.org/wikipedia/commons/d/de/Bananavarieties.jpg'
};
return (
<View style={styles.container}>
<Text>Ssup Dude! Want some bananas?</Text>
<Image source = {pic} style = {{width: 300, height: 300}}/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
You seem to be confused. In react-navigation in order to push a screen, you do not do this.props.navigator.push, you use this.props.navigation.navigate.

Why am I getting an invalid value error?

I don't understand how I'm getting this error (pic below). In my LoginForm.js file, the onEmailChange(text) is giving me an unresolved function or method call to onEmailChange() error when I hover over it in my WebStorm IDE. In my index.js file, no error is being thrown anywhere.
I've looked around SO for this issue but it doesn't fully pertain to my problem.
I've tried File > Invalidate Caches/Restart but that didn't work.
Here's App.js:
import React, { Component } from 'react';
import {StyleSheet} from 'react-native';
import {Provider} from 'react-redux';
import {createStore} from 'redux';
import firebase from 'firebase';
import reducers from './reducers';
import LoginForm from './components/common/LoginForm';
class App extends Component {
render() {
return(
<Provider style={styles.c} store={createStore(reducers)}>
<LoginForm/>
</Provider>
);
}
}
const styles = StyleSheet.create({
c: {
flex: 1
}
});
export default App;
Here's LoginForm.js:
import React, {Component} from 'react';
import {connect} from 'react-redux';
import {emailChanged} from 'TorusTeensApp/src/actions';
import {Text, StyleSheet, KeyboardAvoidingView, TextInput, TouchableOpacity} from 'react-native';
class LoginForm extends Component {
render() {
onEmailChange(text)
{
this.props.emailChanged(text);
}
return(
<KeyboardAvoidingView style={styles.container}>
<TextInput
style={styles.userInput}
onsubmitediting={() => this.passwordInput.focus()}
returnKeyType={"next"}
placeholder={"Email"}
label={"Email"}
keyboardType={"email-address"}
autoCorrect={false}
onChangeText={this.onEmailChange.bind(this)}
value={this.props.email}
/>
<TextInput
style={styles.userInput}
ref={(userInput) => this.passwordInput = userInput}
returnKeyType={"go"}
placeholder={"Password"}
label={"Password"}
secureTextEntry
/>
<TouchableOpacity style={styles.buttonContainer}>
<Text style={styles.buttonText}>Login</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.buttonContainer}>
<Text style={styles.buttonText}>Create Account</Text>
</TouchableOpacity>
</KeyboardAvoidingView>
);
}
}
const styles = StyleSheet.create({
container: {
padding: 20 // creates a gap from the bottom
},
userInput: {
marginBottom: 20,
backgroundColor: '#9b42f4',
height: 40
},
buttonContainer: {
backgroundColor: '#41bbf4',
paddingVertical: 10,
marginBottom: 20
},
buttonText: {
textAlign: 'center',
color: '#FFFFFF'
}
});
const mapStateToProps = state => {
return {
email: state.auth.email
};
};
export default connect(mapStateToProps, null, {emailChanged}) (LoginForm);
Here's index.js:
import {EMAIL_CHANGED} from './types';
export const emailChanged = (text) => {
return {
type: 'EMAIL_CHANGED',
payload: text
};
};
export default emailChanged();
Your connect is miswired
connect(mapStateToProps, null, {emailChanged}) (LoginForm);
It should be something like:
connect(mapStateToProps,
(dispatch) => ({emailChanged: (text) => dispatch(emailChanged(text))})
)(LoginForm);
so that your action actually gets dispatched
and as spotted by emed in comment:
export default emailChanged;
without parentheses.
You defined your callback inside your render() method and not inside the class body. Do it like this:
class LoginForm extends Component {
onEmailChange(text) {
this.props.emailChanged(text);
}
render() {
return(...);
}
}
Also you shouldn't bind methods inside your render() method. Do it in the constructor of your Component:
class LoginForm extends Component {
constructor(props) {
super(props);
this.onEmailChange.bind(this);
}
onEmailChange(text) {
// do something
}
// other methods
}
Or if you use babel and ES6, you can define your callback with an arrow function, then it will be automatically bound:
class LoginForm extends Component {
onEmailChange = text => {
// do something
};
// other methods
}
See also the react docs about autobinding.
Also your call to connect seems incorrect. If you want to dispatch the action emailChanged it has to look like this:
const mapStateToProps = state => {
return {
email: state.auth.email
};
};
const mapDispatchToProps = dispatch => {
// this put a function emailChanged into your props that will dispatch the correct action
emailChanged: text => dispatch(emailChanged(text))
};
const LoginFormContainer = connect(mapStateToProps, mapDispatchToProps)(LoginForm);
export default LoginFormContainer;
The third argument to connect needs to be a function that knows how to merge the output of mapStateToProps, mapDispatchToProps, and ownProps all into one object that is then used as props for your connected component. I think you're trying to pass that action to the mapDispatchToProps argument, which is the second argument not the third. So, based on what I think you're doing, you probably wanna change your connect line to look like this.
export default connect(mapStateToProps, {emailChanged}) (LoginForm);
Then, export the function from your actions file not the output of calling that function.
export default emailChanged;
Notice I removed the parentheses so it's not being called.
Then make the callback function a method on your class and bind it in the constructor.
constuctor(props) {
super(props);
this.onEmailChange = this.onEmailChange.bind(this);
}
onEmailChange(text) {
this.props.emailChanged(text);
}
Then update onChangeText on that element.
onChangeText={this.onEmailChange}

javascript Firebase Simple Authentication in React Native

I'm following a tutorial to make basic sign up/login functionalities for my react native app but am running into a couple issues. My code is as below:
App.js
import React, { Component } from 'react';
'use strict';
import {
AppRegistry,
Text,
StyleSheet,
ActivityIndicator,
View,
} from 'react-native';
import Navigator from 'react-native-deprecated-custom-components';
import Login from './Login';
import Account from './Account';
import * as firebase from 'firebase';
var firebaseConfig = {
apiKey: "MY KEY",
authDomain: "MY DOMAIN",
databaseURL: "MY URL",
storageBucket: "MY BUCKET",
};
const firebaseApp = firebase.initializeApp(firebaseConfig);
import styles from '../styles/mainstyle.js';
export default class App extends Component {
constructor(props){
super(props);
this.state = {
// the page is the screen we want to show the user, we will determine that
// based on what user the firebase apI returns to us.
page: null
};
}
componentWillMount(){
// We must asynchronously get the auth state, if we use currentUser here, it'll be null
const unsubscribe = firebaseApp.auth().onAuthStateChanged((user) => {
// If the user is logged in take them to the accounts screen
if (user != null) {
this.setState({page: Account});
return;
}
// otherwise have them login
this.setState({page: Login});
// unsubscribe this observer
unsubscribe();
});
}
render() {
if (this.state.page) {
return (
// Take the user to whatever page we set the state to.
// We will use a transition where the new page will slide in from the right.
<Navigator
initialRoute={{component: this.state.page}}
configureScene={() => {
return Navigator.SceneConfigs.FloatFromRight;
}}
renderScene={(route, navigator) => {
if(route.component){
// Pass the navigator the the page so it can navigate as well.
// Pass firebaseApp so it can make calls to firebase.
return React.createElement(route.component, { navigator, firebaseApp});
}
}} />
);
} else {
return (
// Our default loading view while waiting to hear back from firebase
<View style={styles.container}>
<View style={styles.body}>
<ActivityIndicator size="large" />
</View>
</View>
);
}
}
}
AppRegistry.registerComponent('App', () => App);
Login.js
'use strict';
import {
AppRegistry,
Text,
TextInput,
View,
TouchableHighlight,
ToolbarAndroid,
ActivityIndicator
} from 'react-native';
import React, {Component} from 'react';
import Signup from './Signup';
import Account from './Account';
import styles from '../styles/mainstyle.js';
import Navigator from 'react-native-deprecated-custom-components';
export default class Login extends Component {
constructor(props){
super(props);
// We have the same props as in our signup.js file and they serve the same purposes.
this.state = {
loading: false,
email: '',
password: ''
}
}
render() {
// The content of the screen should be inputs for a username, password and submit button.
// If we are loading then we display an ActivityIndicator.
const content = this.state.loading ? <ActivityIndicator size="large"/> :
<View>
<TextInput
style={styles.textInput}
onChangeText={(text) => this.setState({email: text})}
value={this.state.email}
placeholder={"Email Address"} />
<TextInput
style={styles.textInput}
onChangeText={(text) => this.setState({password: text})}
value={this.state.password}
secureTextEntry={true}
placeholder={"Password"} />
<TouchableHighlight onPress={this.login.bind(this)} style={styles.primaryButton}>
<Text style={styles.primaryButtonText}>Login</Text>
</TouchableHighlight>
<TouchableHighlight onPress={this.goToSignup.bind(this)} style={styles.transparentButton}>
<Text style={styles.transparentButtonText}>New here?</Text>
</TouchableHighlight>
</View>;
// A simple UI with a toolbar, and content below it.
return (
<View style={styles.container}>
<View style={styles.body}>
{content}
</View>
</View>
);
}
login(){
this.setState({
loading: true
});
// Log in and display an alert to tell the user what happened.
this.props.firebaseApp.auth().signInWithEmailAndPassword(this.state.email, this.state.password
).then((userData) =>
{
this.setState({
loading: false,
username:"Joe"
});
this.props.navigator.push({
component: Account
});
}
).catch((error) =>
{
this.setState({
loading: false
});
alert('Login Failed. Please try again' + error.message);
});
}
// Go to the signup page
goToSignup(){
this.props.navigator.push({
component: Signup
});
}
}
AppRegistry.registerComponent('Login', () => Login);
Account.js
'use strict';
import {
AppRegistry,
StyleSheet,
Text,
View,
Image,
TouchableHighlight,
ToolbarAndroid
} from 'react-native';
import React, {Component} from 'react';
import Login from './Login';
import styles from '../styles/mainstyle.js';
import Navigator from 'react-native-deprecated-custom-components';
// Styles specific to the account page
const accountStyles = StyleSheet.create({
email_container: {
padding: 20
},
email_text: {
fontSize: 18
}
});
export default class Account extends Component {
constructor(props) {
super(props);
this.state = {
loading: true,
}
}
componentWillMount() {
// get the current user from firebase
const userData = this.props.firebaseApp.auth().currentUser;
this.setState({
user: userData,
loading: false
});
console.log(userData);
console.log(this.props.firebaseApp)
console.log(this.props.firebaseApp.auth())
var isNewUser = true;
var ref = this.props.firebaseApp;
ref.onAuthStateChanged(function(authData) {
if (authData && isNewUser) {
// save the user's profile into the database so we can list users,
// use them in Security and Firebase Rules, and show profiles
ref.child("users").child(authData.uid).set({
provider: authData.provider,
name: getName(authData)
});
}
});
// find a suitable name based on the meta info given by each provider
function getName(authData) {
switch(authData.provider) {
case 'password':
return authData.password.email.replace(/#.*/, '');
case 'twitter':
return authData.twitter.displayName;
case 'facebook':
return authData.facebook.displayName;
}
}
}
render() {
// If we are loading then we display the indicator, if the account is null and we are not loading
// Then we display nothing. If the account is not null then we display the account info.
const content = this.state.loading ? <ActivityIndicator size="large"/> :
this.state.user &&
<View style={styles.body}>
<View style={accountStyles.email_container}>
<Text style={accountStyles.email_text}>{this.state.user.email}</Text>
</View>
<TouchableHighlight onPress={this.logout.bind(this)} style={styles.primaryButton}>
<Text style={styles.primaryButtonText}>Logout</Text>
</TouchableHighlight>
<TouchableHighlight onPress={this.logout.bind(this)} style={styles.primaryButton}>
<Text style={styles.primaryButtonText}>Logout</Text>
</TouchableHighlight>
</View>
;
return (
<View style={styles.container}>
<View style={styles.body}>
{content}
</View>
</View>
);
}
logout() {
// logout, once that is complete, return the user to the login screen.
this.props.firebaseApp.auth().signOut().then(() => {
this.props.navigator.push({
component: Login
});
});
}
}
AppRegistry.registerComponent('Account', () => Account);
Signup.js
'use strict';
import {
AppRegistry,
View,
ToolbarAndroid,
ActivityIndicator
} from 'react-native';
import { Header,Title,Container, Content, List, ListItem, InputGroup, Input, Icon, Text, Picker, Button } from 'native-base';
import styles from '../styles/mainstyle.js';
import React, {Component} from 'react';
import Login from './Login';
export default class Signup extends Component {
constructor(props) {
super(props);
this.state = {
// used to display a progress indicator if waiting for a network response.
loading: false,
// entered credentials
email: '',
password: ''
}
}
// A method to passs the username and password to firebase and make a new user account
signup() {
this.setState({
// When waiting for the firebase server show the loading indicator.
loading: true
});
// Make a call to firebase to create a new user.
this.props.firebaseApp.auth().createUserWithEmailAndPassword(
this.state.email,
this.state.password).then(() => {
// then and catch are methods that we call on the Promise returned from
// createUserWithEmailAndPassword
alert('Your account was created!');
this.setState({
// Clear out the fields when the user logs in and hide the progress indicator.
email: '',
password: '',
loading: false
});
this.props.navigator.push({
component: Login
});
}).catch((error) => {
// Leave the fields filled when an error occurs and hide the progress indicator.
this.setState({
loading: false
});
alert("Account creation failed: " + error.message );
});
}
render() {
console.log('hello');
// The content of the screen should be inputs for a username, password and submit button.
// If we are loading then we display an ActivityIndicator.
const content = this.state.loading ? <ActivityIndicator size="large"/> :
<Content>
<List>
<ListItem>
<InputGroup>
<Icon name="person" style={{ color: '#0A69FE' }} />
<Input
onChangeText={(text) => this.setState({email: text})}
value={this.state.email}
placeholder={"Email Address"} />
</InputGroup>
</ListItem>
<ListItem>
<InputGroup>
<Icon name="unlock" style={{ color: '#0A69FE' }} />
<Input
onChangeText={(text) => this.setState({password: text})}
value={this.state.password}
secureTextEntry={true}
placeholder={"Password"} />
</InputGroup>
</ListItem>
</List>
<Button style={styles.primaryButton} onPress={this.signup.bind(this)}>
Signup
</Button>
<Button onPress={this.goToLogin.bind(this)} style={styles.primaryButton}>
Go to Login
</Button>
</Content>
;
// A simple UI with a toolbar, and content below it.
return (
<Container>
<Header>
<Title>Sign Up</Title>
</Header>
{content}
</Container>
)
}
goToLogin(){
this.props.navigator.push({
component: Login
});
}
}
AppRegistry.registerComponent('Signup', () => Signup);
I am getting the following errors:
Error#1:
"Warning: View.propTypes has been deprecated and will be removed in a future version of ReactNative. Use ViewPropTypes instead."
I've been looking through my code and cannot find any reference to View.protoTypes. I'm unsure what this error is referring to.
Error#2:
"Warning: React.createElement: 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 App.
in App
in RCTView (created by View)
in View (created by AppContainer)
in RCTView (created by View)
in View (created by AppContainer)
in AppContainer"
I've looked on this website for a solution for this and have seen people mention that the class export may have been done incorrectly, but looking at my own code I feel like I've done this correctly.
Error#3:
"Error: 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 App."
Same as above, am I exporting my class incorrectly?
the warning #1 could be related to a specific package which uses deprecated or old code (not fully supported by your React version).
I suppose that Issue #2 and #3 may be relative to how you import Navigator rather than how you export some class, try with:
import { Navigator } from 'react-native-deprecated-custom-components';

undefined is not an object error in react native

I'm trying to create a route to a screen by pressing a button in a side menu using react navigation. When I try to implement it, I get the following error:
undefined is not an object (evaluating '_this.props.user.Range')
The error flags, point something wrong in here:
RangeValues: this.props.user.Range
The rest of the components I am trying to navigate to are here:
import React, {Component} from 'react'
import {
StyleSheet,
View,
Text,
Switch,
} from 'react-native'
import Slider from 'react-native-multislider'
export default class Profile extends Component {
state = {
RangeValues: this.props.user.Range,
distanceValue: [this.props.user.distance]
}
render() {
const {name, work, id} = this.props.user
const {RangeValues, distanceValue} = this.state
return (
<View style={styles.container}>
<View style={styles.profile}>
<Text style={{fontSize:20}}>{name}</Text>
</View>
<View style={styles.label}>
<Text>Distance</Text>
<Text style={{color:'darkgrey'}}>{distanceValue}km</Text>
</View>
<Slider
min={1}
max={100}
values={distanceValue}
onValuesChange={val => this.setState({distanceValue:val})}
onValuesChangeFinish={val => this.updateUser('distance', val[0])}
/>
<View style={styles.label}>
<Text>Age Range</Text>
<Text style={{color:'darkgrey'}}>{ageRangeValues.join('-')}</Text>
</View>
<Slider
min={1}
max={200}
values={RangeValues}
onValuesChange={val => this.setState({RangeValues:val})}
onValuesChangeFinish={val => this.updateUser('Range', val)}
/>
</View>
)
}
}
I want to navigate from a button in a drawer using stack navigator, my routing is as follows:
import { StackNavigator } from 'react-navigation';
import React from 'react';
import Home from './screens/home';
import Login from './screens/login';
import Profile from './screens/profile';
const RouteConfigs = {
Login: { screen: Login },
Home: { screen: Home },
Profile: { screen: Profile },
};
const StackNavigatorConfig = {
headerMode: 'none',
}
export default StackNavigator(RouteConfigs, StackNavigatorConfig)
Where I am trying to navigate from is the Home screen component. The function I have used for this within the Home component is:
() => this.props.navigation.navigate('Profile', { user: this.state.user })
Does anybody know how to fix this error in order for me to navigate from the home component to the profile component?
I think you should bind your props from constructor :
export class MyClass extends Component {
constructor(props) {
super(props);
if (!this.state) {
this.state = {
data: props.myData
}
}
render() {DO THE JOB HERE}
}
}
Then you can access to this.state instead of state
For more explanations, props are not yet available since the constructor has not pass. See Component doc : https://facebook.github.io/react/docs/react-component.html#constructor

Categories

Resources