I'm newbie in React-native , I've just confused on how can I go to next page when the Google API successfully load to my app, mostly in the internet they used onPress but I don't have any onPress just to trigger the event instead i've implement after it successfully login data and will trigger the event, how should I do it?
From Login > Home
Apps.js
import React from 'react';
import Login from './components/login'
import SplashScreen from 'react-native-splash-screen';
const App = () => {
React.useEffect(() =>{
SplashScreen.hide()
},[])
return (
<Login/>
)
}
export default App;
Login.js
import React, { Component } from 'react';
import { View, StyleSheet, ToastAndroid, Button ,Text,Image} from "react-native";
import {
GoogleSignin,
GoogleSigninButton,
statusCodes,
} from '#react-native-community/google-signin';
GoogleSignin.configure({
webClientId: 'testttttttt.........apps.googleusercontent.com',
offlineAccess: true,
});
class Login extends Component {
constructor(props){
super(props)
this.state={
userGoogleInfo : {},
loaded: false
}}
signIn = async () => {
try {
console.log("Processing");
await GoogleSignin.hasPlayServices();
const userInfo = await GoogleSignin.signIn();
this.setState({
userGoogleInfo : userInfo,
loaded : true
})
// after this it goes to another page Home.js -----------------------------------------<<<<<<<<<
} catch (error) {
if (error.code === statusCodes.SIGN_IN_CANCELLED) {
console.log("e 1");
} else if (error.code === statusCodes.IN_PROGRESS) {
console.log("e 2");
} else if (error.code === statusCodes.PLAY_SERVICES_NOT_AVAILABLE) {
console.log("e 3");
} else {
console.log(error.message);
}
}
};
render() {
return (
<View style={styles.container}>
<GoogleSigninButton
style={{ width: 222, height: 48 }}
size={GoogleSigninButton.Size.Wide}
color={GoogleSigninButton.Color.Dark}
onPress={this.signIn}
/>
{this.state.loaded ?
<View>
<Text>{this.state.userGoogleInfo.user.name}</Text>
<Text>{this.state.userGoogleInfo.user.email}</Text>
<Image
style={{ width: 100, height: 100 }}
source={{uri: this.state.userGoogleInfo.user.photo}}
/>
</View>
: <Text>Not SignedIn</Text> }
</View>
);
}
}
const styles = StyleSheet.create({
container:{
flex:1,
backgroundColor:'#000000',
padding:15,
},
});
export default Login;
Home.js
import React from 'react';
import Login from './components/login'
import SplashScreen from 'react-native-splash-screen';
import { View,Text} from "react-native";
const App = () => {
React.useEffect(() =>{
SplashScreen.hide()
},[])
return (
<View>
<Text>fsaf</Text>
</View>
)
}
export default App;
You can use React Navigation
And once you have a proper setup use push method
navigation.push('YourView')
First, you need to add a navigation component to your project. The React Native documentation has a section about it with some libraries suggestions.
The React Navigation is hugely used and has the CommonActions that resolve your problem. After installing the React Navigation you can see this section on the documentation to dispatch the CommonActions to navigate to the Home screen after login success on your try...catch.
Related
I've been following some simple tutorial (full working source code) to get the idea how to use React's Context together with handling authentication in my React Native app.
This example is using stateful components for views and handling routing the app within component itself, for example, in SignInScreen.js:
/* SignInScreen.js */
export default class SignInScreen extends React.Component {
static navigationOptions = {
title: 'Please sign in',
};
_signInAsync = async (saveToken) => {
saveToken()
.then((data) => {
// ROUTE USER TO "PROTECTED" PART OF THE APP
this.props.navigation.navigate('App');
})
.catch((error) => {
this.setState({ error })
})
};
render() {
return (
<View style={styles.container}>
<MyContext.Consumer>
{context => ((
<Button title="Sign in!" onPress={() => this._signInAsync(context.saveToken)} />
))}
</MyContext.Consumer>
</View>
);
}
};
I tried to transform this component into function component and move the signing in logic into my Context Provider like this:
/* SignInScreen.js - MODIFIED */
import React from 'react';
import { Button, View } from 'react-native';
import { MyContext } from '../Provider';
export default const LoginScreen = () => {
return (
<View>
<MyContext.Consumer>
{context => {
return (
<Button
onPress={() => context.signIn()}
title="Sign In"
/>
)
}
}
</MyContext.Consumer>
</View>
)
};
/* Provider.js */
import React from 'react';
import { AsyncStorage } from 'react-native';
export const MyContext = React.createContext();
export default class MyProvider extends React.Component {
constructor(props) {
super(props);
this.getToken = () => AsyncStorage.getItem('userToken');
this.saveToken = () => AsyncStorage.setItem('userToken', 'abc');
this.removeToken = () => AsyncStorage.removeItem('userToken');
this.signIn = () => {
this.saveToken()
.then((data) => {
// this.props.navigation DOES NOT EXIST!!! :(
this.props.navigation.navigate('App');
})
.catch((error) => this.setState({ error }));
};
this.state = {
token: '',
signIn: this.signIn,
};
}
componentWillMount() {
AsyncStorage.getItem('userToken')
.then((token) => {
this.setState({ token })
})
.catch(error => {
this.setState({ error })
})
}
render() {
return (
<MyContext.Provider value={this.state}>
{this.props.children}
</MyContext.Provider>
);
}
}
When I press that "Sign In" button, my provider errors when I try to redirect user (this.props.navigation.navigate('App');) because this.props.navigation does not exist.
As far as I understood, this is happening because I didn't properly wrap my app with my Context.
This is my main App.js file:
/* App.js */
import React from 'react';
import { View } from 'react-native';
import MyContext from './Provider';
import AppNavigator from './navigation/AppNavigator';
export default class App extends React.Component {
render() {
return (
<MyContext>
<View>
<AppNavigator />
</View>
</MyContext>
);
}
}
and my AppNavigator.js:
/* AppNavigator.js */
import React from 'react';
import { createAppContainer, createSwitchNavigator } from 'react-navigation';
import AuthLoadingScreen from '../screens/AuthLoadingScreen';
import Auth from './AuthNavigator';
import App from './AppTabNavigator';
export default createAppContainer(createSwitchNavigator(
{
AuthLoading: AuthLoadingScreen,
Auth,
App,
},
{
initialRouteName: 'AuthLoading',
}
));
(AuthNavigator and AppTabNavigator contain only createStackNavigator() with my screens defined in it.)
My question is: how can I wrap this app with my Context so that Context Provider is always aware of navigation prop and so I could handle logging in and out and routing user from the Context Provider itself?
I solved this by using NavigationActions, pretty helpful built-in module designed for this purpose.
I have a TypeForm integrated with my app and this type form opens in a WebView. The process goes like when I Sign up, a type form opens in a WebView. On form submit I want it to be redirected to home screen.
Here is my code:
import React, { Component } from 'react';
import {
StyleSheet,
Text,
View,
TouchableOpacity,
ScrollView,
WebView,
Linking
} from 'react-native';
import Constants from '../constants';
import NavigationBar from 'react-native-navbar';
import Icon from 'react-native-vector-icons/FontAwesome';
import { connect } from "react-redux";
import { bindActionCreators } from "redux";
import * as userActions from '../redux/modules/user';
type Props = {};
class Typeform extends Component<Props> {
constructor(props){
super(props);
this.state={
}
// console.log('props ******* next_lottery_time constructor ******** ',props)
}
render() {
const { navigate, goBack } = this.props.navigation;
const titleConfig = {
title: 'SURVEY',
tintColor:Constants.Colors.White
};
const uri = 'https://threadest1.typeform.com/to/vjS2Nx';
return (
<View style={{flex:1}}>
<NavigationBar
title={titleConfig}
style={{backgroundColor: 'rgb(32,73,157)'}}
statusBar={{hidden:false,tintColor:'rgb(32,73,157)'}}
leftButton={<TouchableOpacity style={{marginLeft:Constants.BaseStyle.DEVICE_WIDTH/100*2.5,marginTop:Constants.BaseStyle.DEVICE_HEIGHT/100*.8}} onPress={()=>goBack()}><Icon color={Constants.Colors.White} name='chevron-circle-left' size={30} /></TouchableOpacity>} />
<WebView
ref={(ref) => { this.webview = ref; }}
source={{ uri }}
onNavigationStateChange={(event) => {
if (event.url !== uri) {
this.webview.stopLoading();
Linking.openURL(event.url);
}
}}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
//justifyContent: 'center',
alignItems: 'center',
}
});
const mapDispatchToProps = dispatch => ({
userActions: bindActionCreators(userActions, dispatch)
});
export default connect(null, mapDispatchToProps)(Typeform);
I am using react-navigation for screen navigation purpose.
This all you can do it in on navigation state change so when you submit from that will return an response and that response you can capture and on that condition you can navigate to another screen.
i my scenario i am using for payment with instamojo.
import React, { Component } from "react";
import { Text, View, StyleSheet, WebView } from "react-native";
import { BASE_URL } from "../../../constants/apiList";
import SecondaryHeader from "../../common/SecondaryHeader";
class Payment extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
refreshing: false,
isPiad: false,
packages: []
};
}
getParameterByName(name, url) {
name = name.replace(/[\[\]]/g, "\\$&");
var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
results = regex.exec(url);
if (!results) {
return null;
}
if (!results[2]) {
return "";
}
return decodeURIComponent(results[2].replace(/\+/g, " "));
}
onNavigationStateChange = eve => {
if (eve.loading !== this.state.isLoading) {
this.setState({
isLoading: eve.loading
});
}
if (eve.url.indexOf("api/orders/") > -1) {
this.props.navigation.replace("paymentStatus", {
url: eve.url,
id: this.props.navigation.state.params.id
});
}
};
render() {
return (
<View style={styles.container}>
<SecondaryHeader title="PAYMENT" {...this.props} />
<WebView
source={{ uri: this.props.navigation.state.params.url }}
onNavigationStateChange={this.onNavigationStateChange}
style={{ height: 200 }}
startInLoadingState={true}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1
}
});
export default Payment;
so after payment instamojo will redirect to payment success of fail page that time i am capturing url and checking if success redirection is there then i am navigating to my payment status screen/
If you are using StackNavigator from react-navigation redirection or switch screens are really easy. you just need to call like the following code after your success response.
StackNavigator will look like
const Stacker = StackNavigator(
{
Landing: {
path: "Landing",
screen: LandingDrawer
}
},
{
initialRouteName: this.state.isLoggedIn,
headerMode: "none",
navigationOptions: {
headerVisible: false
}
}
);
Redirection
const resetAction = NavigationActions.reset({
index: 0,
actions: [
NavigationActions.navigate({
routeName: "Landing"
})
]
});
this.props.navigation.dispatch(resetAction);
this is what I used in my app, hope this will help you
Have you looked at using the React wrapper around Typeform Embed SDK?
It seems to be the way to go for what you want to achieve.
You can listen to onSubmit event that will be triggered when the typeform is submitted and then do the redirection.
The code would look like this
import React from 'react';
import { ReactTypeformEmbed } from 'react-typeform-embed';
class App extends React.Component {
render() {
return <ReactTypeformEmbed url={'https://demo.typeform.com/to/njdbt5'} onSubmit='alert("form submitted");'/>
}
}
Hope it helps
I have three .js files in my react native project:
App.js
LoginPage.js
RootNavigation.js
My launcher screen is LoginPage.js now i need to go to Rootnavigation.js .
RootNavigation.js has import MainTabnavigator.js
App.js:
import React from 'react';
import { Platform, StatusBar, StyleSheet, View } from 'react-native';
import { AppLoading, Asset, Font } from 'expo';
import { Ionicons } from '#expo/vector-icons';
import RootNavigation from './navigation/RootNavigation';
import LoginPage from './screens/LoginPage';
import { createSwitchNavigator, createStackNavigator } from 'react-navigation';
export class App extends React.Component {
state = {
isLoadingComplete: false,
};
render() {
if (!this.state.isLoadingComplete && !this.props.skipLoadingScreen) {
return (
<AppLoading
startAsync={this._loadResourcesAsync}
onError={this._handleLoadingError}
onFinish={this._handleFinishLoading}
/>
);
} else {
return (
<View style={styles.container}>
{Platform.OS === 'ios' && <StatusBar barStyle="default" />}
<RootNavigation />
</View>
);
}
}
_loadResourcesAsync = async () => {
return Promise.all([
Asset.loadAsync([
require('./assets/images/robot-dev.png'),
require('./assets/images/robot-prod.png'),
]),
Font.loadAsync({
// This is the font that we are using for our tab bar
...Ionicons.font,
// We include SpaceMono because we use it in HomeScreen.js. Feel free
// to remove this if you are not using it in your app
'space-mono': require('./assets/fonts/SpaceMono-Regular.ttf'),
}),
]);
};
_handleLoadingError = error => {
// In this case, you might want to report the error to your error
// reporting service, for example Sentry
console.warn(error);
};
_handleFinishLoading = () => {
this.setState({ isLoadingComplete: true });
};
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
},
});
export default justsms = createStackNavigator(
{
First: { screen: LoginPage },
Second: { screen: App }
});
LoginPage.js:
import React from 'react';
import {Image, Platform, ScrollView, StyleSheet, Text, TouchableOpacity, View, Button} from 'react-native';
export default class LoginPage extends React.Component {
static navigationOptions={
title:'Login Page'
};
NavigateActivityFunction = () =>
{
this.props.navigation.navigate('Second');
}
render(){
return(<View style={styles.container}>
<Button title='Tab Activity' onPress={this.NavigateActivityFunction}/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
justifyContent:'center'
}
});
RootNavigation.js:
import React from 'react';
import { Notifications } from 'expo';
import { createSwitchNavigator } from 'react-navigation';
import MainTabNavigator from './MainTabNavigator';
import registerForPushNotificationsAsync from '../api/registerForPushNotificationsAsync';
const AppNavigator = createSwitchNavigator({
// You could add another route here for authentication.
// Read more at https://reactnavigation.org/docs/en/auth-flow.html
Main: MainTabNavigator,
});
export default class RootNavigation extends React.Component {
componentDidMount() {
this._notificationSubscription = this._registerForPushNotifications();
}
componentWillUnmount() {
this._notificationSubscription && this._notificationSubscription.remove();
}
render() {
return <AppNavigator />;
}
_registerForPushNotifications() {
// Send our push token over to our backend so we can receive notifications
// You can comment the following line out if you want to stop receiving
// a notification every time you open the app. Check out the source
// for this function in api/registerForPushNotificationsAsync.js
registerForPushNotificationsAsync();
// Watch for incoming notifications
this._notificationSubscription = Notifications.addListener(this._handleNotification);
}
_handleNotification = ({ origin, data }) => {
console.log(`Push notification ${origin} with data: ${JSON.stringify(data)}`);
};
}
MainTabNavigator.js:
import React from 'react';
import { Platform } from 'react-native';
import { Ionicons } from '#expo/vector-icons';
import { createStackNavigator, createBottomTabNavigator } from 'react-navigation';
import TabBarIcon from '../components/TabBarIcon';
import HomeScreen from '../screens/HomeScreen';
import LinksScreen from '../screens/LinksScreen';
import SettingsScreen from '../screens/SettingsScreen';
const HomeStack = createStackNavigator({
Home: HomeScreen,
});
HomeStack.navigationOptions = {
tabBarLabel: 'Home',
tabBarIcon: ({ focused }) => (
<TabBarIcon
focused={focused}
name={
Platform.OS === 'ios'
? `ios-information-circle${focused ? '' : '-outline'}`
: 'md-information-circle'
}
/>
),
};
const LinksStack = createStackNavigator({
Links: LinksScreen,
});
LinksStack.navigationOptions = {
tabBarLabel: 'Links',
tabBarIcon: ({ focused }) => (
<TabBarIcon
focused={focused}
name={Platform.OS === 'ios' ? `ios-link${focused ? '' : '-outline'}` : 'md-link'}
/>
),
};
const SettingsStack = createStackNavigator({
Settings: SettingsScreen,
});
SettingsStack.navigationOptions = {
tabBarLabel: 'Settings',
tabBarIcon: ({ focused }) => (
<TabBarIcon
focused={focused}
name={Platform.OS === 'ios' ? `ios-options${focused ? '' : '-outline'}` : 'md-options'}
/>
),
};
export default createBottomTabNavigator({
HomeStack,
LinksStack,
SettingsStack,
});
Here when i click on button in LoginPage.js it should go to tab activity . I tried importing MainTabNavigator.js in App.js but when i click on button nothing is happening. I would be glad if someone Help me in this issue.
I have recently started out with React native and stuck with this.
I wanted to make a login system so I used conditional rendering to render Login Screen and App's Main screen separately based on LoggedInStatus State.
root component:
import React, {Component} from 'react';
import { StyleSheet, Platform, Image, Text, View, ActivityIndicator, AsyncStorage } from 'react-native';
import firebase from 'react-native-firebase'; import SQLite from 'react-native-sqlite-storage'; import Login from './src/screens/Login'; import Home from './src/screens/Home'; import SplashScreen from 'react-native-smart-splash-screen' var db = SQLite.openDatabase({name: 'test.db', createFromLocation:'~sqlite.db'})
export default class App extends Component { constructor(props) {
super(props);
this.state = {
loggedInStatus: false}; };
componentWillMount(){
//SplashScreen.close(SplashScreen.animationType.scale, 850, 500)
SplashScreen.close({
animationType: SplashScreen.animationType.fade,
duration: 450,
delay: 500,
})
db.transaction((tx) => {
tx.executeSql('SELECT * FROM users', [], (tx, results) => {
console.log("Query completed");
var len = results.rows.length;
console.log(len);
if (len > 0) {
console.log("User is Logged in");
this.setState({ loggedInStatus: true });
}
else{
console.log("User is Logged out");
this.setState({ loggedInStatus: false });
}
});
}); };
render() {
if (this.state.loggedInStatus === true) {
return <Home logoutProp={{ LoggedOut: () => this.setState({ loggedInStatus: false }) }}/>
}
else if (this.state.loggedInStatus === false){
return <Login screenProps={{ isLoggedIn: () => this.setState({ loggedInStatus: true }) }}/>
}
return (
<View>
<Text>This is SpashScreen</Text>
</View>
); } }
Now, If user is logged in then Home component is rendered, Home component is a Drawer navigator with Main screen and Drawer screen:
Home Component:
import React from 'react';
import {
DrawerNavigator,
StackNavigator,
TabNavigator
} from 'react-navigation';
import Icon from 'react-native-vector-icons/Ionicons';
import Main from '../src/tabs/Main';
// import Settings from './src/tabs/Settings';
// import Profile from './src/screens/Profile';
import Modal from '../src/screens/Modal';
import Drawer from '../src/components/Drawer';
export default DrawerNavigator({
Home: {
screen: Main,
}
},{
contentComponent: props => <Drawer {...props} />
});
My Drawer Component has a logout button, I need to call logoutProp of the root component onclick of logout button of the Drawer component, how can I achieve this?
Drawer Component:
import React, { Component } from 'react';
import {
Button,
StyleSheet,
Text,
View
} from 'react-native';
import SQLite from 'react-native-sqlite-storage';
var db = SQLite.openDatabase({name: 'test.db', createFromLocation:'~sqlite.db'})
export default class Drawer extends Component {
constructor(props) {
super(props);
}
render() {
return (
<View style={styles.container}>
<View style={styles.header}>
</View>
<View style={styles.body}>
<Button
title="Log Out"
onPress={this.logout}
/>
</View>
</View>
);
}
logout(){
//Need some method to call logoutProp of root component
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#F5F5F5',
},
header: {
flex:1,
backgroundColor: '#1d337d'
},
body: {
flex:3,
}
});
Any help will be appreciated, Thanks :)
I am trying to print text content of login.php into the screen via "var result", but the fetch function won't alter value of "var result". How can I set value of result from output of the fetch function?
import React, { Component } from 'react';
import {
StyleSheet,
Text,
View,
StatusBar,
} from 'react-native';
import Logo from '../components/Logo';
import Form from '../components/Form';
import loginapi from '../apis/loginapi';
var result='noresult';
export default class Login extends Component<{}> {
render() {
login();
return (
<View style={styles.container}>
<Logo/>
<Form/>
<Text>
{result}
</Text>
<Text>
</Text></View>
);
}
}
function login() {
result = fetch('https://www.skateandstrike.com/loginsv/login.php').then((text) => {return text;});
}
const styles = StyleSheet.create({
container : {
backgroundColor:'#f05545',
flex: 1,
alignItems:'center',
justifyContent:'center',
}
});
function myFunction() {
this.setState({ showLoading: false });
}
This is not working too, using setState:
import React, { Component } from 'react';
import {
StyleSheet,
Text,
View,
StatusBar,
} from 'react-native';
import Logo from '../components/Logo';
import Form from '../components/Form';
import loginapi from '../apis/loginapi';
export default class Login extends Component<{}> {
constructor(){
super();
this.state = {
data:'NoData',
}
}
render() {
login();
return (
<View style={styles.container}>
<Logo/>
<Form/>
<Text>
{this.state.data}
</Text>
</View>
);
}
}
function login() {
fetch('https://www.skateandstrike.com/loginsv/login.php').then(data => this.setState(data));
}
const styles = StyleSheet.create({
container : {
backgroundColor:'#f05545',
flex: 1,
alignItems:'center',
justifyContent:'center',
}
});
function myFunction() {
this.setState({ showLoading: false });
}
Am I using setState in a wrong way? Thanks in advance for your help.
When using the fetch API, I'd recommend using a promise, and you parse it if you are setting the state.
React re-renders on state/props change.
sample code:
fetch(url)
.then(data => data.json()) // if needed
.then(data => this.setState(data))
remember to set state in the constructor.