Skip to content

Instantly share code, notes, and snippets.

@kingsleytagbo
Created October 22, 2020 21:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kingsleytagbo/f0a4886614563c2b0b80db246be5a9ff to your computer and use it in GitHub Desktop.
Save kingsleytagbo/f0a4886614563c2b0b80db246be5a9ff to your computer and use it in GitHub Desktop.
React Native - Login Form Function Component
const API_URL = 'https://nodejsappapi.herokuapp.com';
const mockSuccess = (value:any) => {
return new Promise((resolve) => {
setTimeout(() => resolve(value), 2000);
});
};
const mockFailure = (value:any) => {
return new Promise((resolve, reject) => {
setTimeout(() => reject(value), 2000);
});
};
export const login = (email:string, password:string, useApi:boolean = true) => {
// console.log({'Login': {email: email, password:password, useApi: useApi}});
if (useApi) {
if ((email && email !== '') && (password && password !== '')) {
const body = {
"login": {
"username": email,
"password": password
}
};
return post('/login', body);
//return mockSuccess({ auth_token: 'Login Api - Success!' });
}
else {
return mockFailure({ error: 500, message: 'Login Api - Failure' });
}
}
else{
return mockFailure({ error: 500, message: 'Login - Failure' });
}
};
export const createAccount = (email:string, password:string, shouldSucceed = true) => {
console.log(email, password);
if (!shouldSucceed) {
return mockFailure({ error: 500, message: 'Something went wrong!' });
}
return mockSuccess({ auth_token: 'successful_fake_token' });
};
const getAuthenticationToken = () => 'successful_fake_token';
export const getUsers = (shouldSucceed = true) => {
const token = getAuthenticationToken();
if (!shouldSucceed) {
return mockFailure({ error: 401, message: 'Invalid Request' });
}
return mockSuccess({
users: [
{
email: 'test@test.ca',
},
{
email: 'test2@test.ca',
},
],
});
};
export const post = async (destination:string, body:any) => {
const headers = {
Accept: 'application/json',
'Content-Type': 'application/json; charset=utf-8',
};
const result = await fetch(`${API_URL}${destination}`, {
method: 'POST',
headers: {
"Content-Type": "text/plain"
},
body: JSON.stringify(body),
});
// console.log({result:result, body: result.body});
if (result.ok) {
const response = result.json();
return response;
}
throw { error: result.status };
};
//#region "Comments"
/**
* React Native - Login Form Function Component
* Author: Kingsley Tagbo
* Github: https://github.com/kingsleytagbo
* Twitter: https://twitter.com/kingsleytagbo
* Website: http://www.launchfeatures.com
* Gists: https://gist.github.com/kingsleytagbo
* Description:
* LoginForm is a ReactNative function component
* Includes React Native ScrollView, StyleSheet, TextInput, TextStyle, View, Text & Button
* useState:
* Hooks are a new addition in React 16.8. They let you use state and other React features
* without writing a class. Hooks don’t work inside classes. But you can use them instead
* of writing classes. A Hook is a special function that lets you “hook into” React features.
* For example, useState is a Hook that lets you add React state to function components.
* Normally, variables “disappear” when a function exits but state variables are preserved
* between re-renders,.
* References:
* Using the State Hook: https://reactjs.org/docs/hooks-state.html
*/
//#endregion "Comments"
import React, { useState } from 'react';
import { ScrollView, StyleSheet, TextInput, TextStyle } from 'react-native';
import { Ionicons } from '@expo/vector-icons';
import { View, Text, Button } from '../../components/Themed';
import Colors from '../../constants/Colors';
import Login from '../../models/Login';
import { setToken } from '../../services/Token';
/**
* LoginForm Function Component
* @param buttonText: text displayed on the Login Button
* @param onSubmit: function called when the Login Button is pressed / clicked
* @param onSuccess: function called when the Login Api call succeeds
* @param onFailure: function called when the Login Api call fails
*/
const LoginForm = ({ buttonText, children, onSubmit, onSuccess, onFailure }:Login) => {
/**
* Declare state variables (email, password, errorMessage), with initial empty values ('')
* and the function that updates them using “array destructuring”
*/
const [email, onChangeEmail] = useState('');
const [password, onChangePassword] = useState('');
const [errorMessage, setErrorMessage] = useState('');
/**
* Called by the Login Button on a Press / Click. Calls the onSubmit function (parameter)
*/
const submit = () => {
onSubmit(email, password)
.then(async (result:any) => {
/**
* On Success of Login authentication, save the authentication / login token
* Calls the onSuccess function (parameter)
*/
if (result.authenticated == true) {
await setToken(result.auth_token);
onSuccess();
}
else{
/**
* On Failure of Login authentication, clear the authentication token
* Calls the onFailure function (parameter)
*/
await setToken(null);
onFailure();
}
})
.catch((res: any) => {
/**
* On Failure of Login Api call, display an error message
*/
setErrorMessage(res.error);
})
};
return (
<ScrollView contentContainerStyle={styles.container}>
<View style={styles.label}><label><Ionicons name="ios-people" />UserName:</label>
<TextInput
style={styles.textInput}
onChangeText={(text: any) => onChangeEmail(text)}
value={email}
placeholder="Enter your Username ..."
keyboardType="email-address"
/>
</View>
<View style={styles.label}><label><Ionicons name="ios-key" />Password:</label>
<TextInput
style={styles.textInput}
onChangeText={(text: any) => onChangePassword(text)}
value={password}
placeholder="Enter your Password ..."
secureTextEntry
/>
</View>
<Button
style={{ color: 'White', backgroundColor: 'White', }}
title={buttonText} onPress={submit} />
{errorMessage ? <Text>{errorMessage}</Text> : null}
{children}
</ScrollView>
);
};
const TextInputStyle:TextStyle = {
height: '2em',
width: 300,
fontSize: 14,
borderColor: Colors.light.tint,
borderWidth: 1,
marginTop: 2,
marginBottom: '1em',
paddingStart: '0.5em',
paddingBottom: '0.5em',
paddingTop: '0.5em',
color: 'Colors.light.tint'
};
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
input: {
height: '2em',
width: 300,
fontSize: '1em',
borderColor: Colors.light.tint,
borderWidth: 1,
marginTop: 2,
marginBottom: '1em',
paddingStart: '0.5em',
paddingBottom: '0.5em',
paddingTop: '0.5em',
color: Colors.light.tint,
selectionColor:"#FFFFFF",
placeholderTextColor:'gray'
},
textInput: TextInputStyle,
label: { height: '2em', fontSize: '1em', marginBottom: '2em', color: '#191970', fontWeight:'normal'}
});
export default LoginForm;
import React, { useState } from 'react';
import { View, Text, Button } from '../components/Themed';
import { StyleSheet } from 'react-native';
import { login } from '../services/Api';
import LoginForm from '../components/forms/LoginForm';
type Props = {
navigation: any;
};
const LoginScreen = ({ navigation }: Props) => {
const [errorMessage, setErrorMessage] = useState('');
const [authenticated, setAuthenticated] = useState(false);
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
{/*
<Text>LoginScreen</Text>
<Button title="Log in" onPress={loginUser} />
*/}
<LoginForm
buttonText="Log-In"
onSubmit={login}
onSuccess={() => {
setErrorMessage("Your are logging-in ...");
setAuthenticated(true);
navigation.navigate('Home');
}}
onFailure = {() => { setErrorMessage("Your username or password is invalid!"); }}
>
{
(authenticated !== null) && (authenticated === true) && (
<Button
style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}
title="Create account"
onPress={() => navigation.navigate('CreateAccount')}
/>
)
}
{errorMessage ? <Text style={{ color: 'red' }}>{errorMessage}</Text> : null}
</LoginForm>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
title: {
fontSize: 20,
fontWeight: 'bold',
},
separator: {
marginVertical: 30,
height: 1,
width: '80%',
},
});
export default LoginScreen;
/*
Url: https://react-native-community.github.io/async-storage/
Async Storage is asynchronous, unencrypted, persistent,
key-value storage solution for your React Native application.
**/
import AsyncStorage from '@react-native-community/async-storage';
export const getToken = async () => {
try {
const value = await AsyncStorage.getItem('@auth_token');
if (value !== null) {
return value;
}
} catch (e) {
return null;
}
};
export const setToken = async (token:any) => {
try {
await AsyncStorage.setItem('@auth_token', token);
} catch (e) {
return null;
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment