Created
October 22, 2020 21:47
-
-
Save kingsleytagbo/f0a4886614563c2b0b80db246be5a9ff to your computer and use it in GitHub Desktop.
React Native - Login Form Function Component
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 }; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//#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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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