Apa jadinya apabila informasi yang bersifat pribadi dapat diakses secara publik yang bukan merupakan pemilik informasi tersebut? Maka dalam kondisi seperti ini, fitur authentication akan sangat dibutuhkan untuk menangani masalah permission untuk user yang akan menggunakan aplikasi kita. Melanjutkan case sebelumnya, membuat aplikasi chatting react native (baca: Jadi, silahkan baca artikel sebelumnya. Apabila kamu sudah tahu cara kerja dari React Native, maka kamu dapat langsung mendownload source codenya saja yang sudah saya lampirkan pada artikel sebelumnya), kita akan menambahkan fitur authentication sebelum user dapat melakukan chatting pada aplikasi whatsapp clone.
Baca Juga: Membuat Aplikasi Chatting React Native
Tahap Persiapan
Sebelum kita membuat fitur authentication menggunakan React Native, maka langkah pertama yang harus dilakukan adalah mengaktifkan service authentication di Firebase. Masih menggunakan project Firebase sebelumnya, lakukan beberapa hal berikut:
-
Pada menu di sisi kiri, pilih Authentication
-
Kemudian pilih tab SIGN-IN METHOD
-
Kemudian Enable pada bagian Email/Password
Setelah kebutuhan terakait service Firebase telah diaktifkan, maka tiba saatnya untuk berinteraksi dengan React Native. Authentication, selalu berkaitan dengan Login & Sing Up, dua hal yang saling terkait satu sama lainnya. Maka pada kesempatan kali ini kita akan membuat keduanya agar dapat digunakan sebagaimana mestinya.
Login & Sign Up Screen
Sebelum beranjak pada topik sub heading diatas, kita akan mengatur route terlebih dahulu yang akan bertindak sebagai navigasi dalam aplikasi yang akan kita bangun. Oleh karena itu, buka file src/config/routes.js
kemudian modifikasi menjadi seperti berikut:
import React from 'react';
import Login from '../screens/Login';
import Signup from '../screens/Signup';
import Home from '../screens/Home';
import ChatScreen from '../screens/ChatScreen';
const routes = {
login: { screen: Login },
signup: { screen: Signup },
home: { screen: Home },
chat: { screen: ChatScreen }
}
export default routes;
Cara kerja dari code diatas masih sama, yakni mengatur navigasi untuk berpindah antar screen. Perlu diperhatikan, kita meng-import dua screen tambahan (baca: Login dan Singup), maka buat file tersebut satu persatu. Pertama, buat file Login.js di dalam folder screens
kemudian ketikkan code berikut:
import React from 'react';
import { login } from '../services/api';
import { View, StyleSheet, Image, ScrollView, TextInput, Button, Text, TouchableOpacity } from 'react-native';
import SplashScreen from '../components/SplashScreen';
import { NavigationActions } from 'react-navigation';
export default class Login extends React.Component {
render() {
return(
<View style={styles.container}>
<Image
style={[ styles.logo ]}
source={require('../assets/img/whatsapplogo.png')} />
<ScrollView style={styles.container}>
<TextInput
ref={(textInput) => this._user = textInput }
style={styles.inputField}
value={this.state.text}
onChangeText={(user) => this.setState({user})}
onSubmitEditing={(event) => this._password.focus()}
onFocus={ () => this.clearValidationErrors() }
editable={true}
maxLength={40}
multiline={false}
placeholder="Masukkan Email"
/>
<TextInput
ref={(textInput) => this._password = textInput }
style={styles.inputField}
value={this.state.text}
onChangeText={(password) => this.setState({password})}
onSubmitEditing={(event) => this.submit()}
editable={true}
secureTextEntry={true}
maxLength={40}
multiline={false}
placeholder="Masukkan Password"
/>
{ this.state.error &&
<View style={styles.validationErrors}>
<Text style={styles.error}>{this.state.error}
</Text>
</View>
}
<View style={styles.buttonStyle}>
{ this.state.loading ?
<SplashScreen /> :
<Button
onPress={() => this.submit()}
title="Masuk" />
}
</View>
<View style={styles.redirectLink}>
<Text>Tidak punya akun? </Text>
<TouchableOpacity onPress={() =>
this.props.navigation.navigate('signup')}>
<Text style={styles.link}>Daftar</Text>
</TouchableOpacity>
</View>
<View style={styles.copyright}>
<Text style={{fontSize: 18, color: '#19B5FE'}}>https://daengweb.id</Text>
</View>
</ScrollView>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'white'
},
logo: {
width: '100%',
height: 200
},
inputField: {
marginTop: 20,
alignSelf: 'center',
height: 55,
width: '80%',
backgroundColor: '#FAFAFA',
borderWidth: 1,
paddingHorizontal: 10,
borderRadius: 10,
borderColor: "#CACACA"
},
redirectLink: {
marginTop: 20,
flex: 1,
flexDirection: 'row',
alignSelf: 'center'
},
link: {
color: 'blue'
},
validationErrors: {
flexDirection: 'row',
justifyContent: 'center',
},
error: {
marginTop: 10,
textAlign: 'center',
color: 'red'
},
buttonStyle: {
marginTop: 15,
flex: 1
},
copyright: {
marginTop: 15,
flex: 1,
alignSelf: 'center'
}
})
Penjelasan: Pada layer pertama akan me-load gambar menggunakan Image
component dari directory src/assets/img/whatsapplogo.png
yang dapat kamu download di Github. Pada layer kedua, kita memiliki dua buah TextInput
component yang diapit oleh ScrollView
component agar pada device yang tidak dapat me-load component secara penuh dapat di-scroll. Adapun properti yang mengikuti TextInput
masih sama seperti sebelumnya, yang membedakan hanya pada bagian TextInput
untuk password terdapat prop secureTextEntry
yang berfungsi untuk mengatur apakah text pada input field akan ditampilkan atau tidak.
Pada layer selanjutnya yang terletak dibawah input field, terdapat bagian yang akan menampilkan errors yang diperoleh dari Firebase:
{ this.state.error &&
<View style={styles.validationErrors}>
<Text style={styles.error}>{this.state.error}
</Text>
</View>
}
Kita juga memiliki sebuah Button
yang menggunkan event onpress, dimana ketika tombol tersebut ditekan maka akan memicu submit
function. Sedangkan untuk function submit
akan kita tambahkan nanti sebab memiliki penjelasan tersendiri agar tidak kebingungan. Kemudian di layer terakhir, kita memiliki memiliki tombol untuk berpindah ke Sign Up screen.
Masih di dalam file Login.js, tambahkan code berikut yang merupakan function submit:
async submit(){
try {
const response = await login(this.state.user, this.state.password);
if (response) {
this.setState({loading: true})
setTimeout(() => {
this.clearAndNavigate('home')
}, 1000);
}
} catch ({ message }) {
this.setState({
error: message
})
}
}
Penjelasan: Kita menggunakan method login yang didapatkan dari service/api.js
dengan mengirimkan parameter state user dan password. Apabila response
bernilai true, maka state loading
akan diset ke true, kemudian dalam waktu satu menit kedepan akan mengirimkan parameter home
ke clearAndNavigate
function. Apabila authentication gagal, maka state error akan diset dengan value message
(baca: message
ini berisi pesan error yang didapatkan dari Firebase).
Buat function berikutnya yang bernama clearAndNavigate
:
clearAndNavigate(screen) {
this.setState({
user: '',
password: ''
})
Keyboard.dismiss();
this.isAuthenticated = true;
this.props.navigation.dispatch(
NavigationActions.reset({
index: 0,
actions: [
NavigationActions.navigate({ routeName: 'home' })
]
})
);
}
Penjelasan: Function ini berfungsi untuk membersihkan state username dan password menggunakan setState
. Kemudian, kita menutup keyboard dan menentukan nilai dari state isAuthenticated
menjadi true, kemudian kita me-replace navigation screen dengan home screen. Kondisi yang diharapkan adalah dimana user tidak diizinkan untuk kembali ke Login atau SignUp screen, jadi kita menggunakan teknik dispatch navigation actions untuk mengimplementasikannya.
Ada yang ketinggalan, pada TextInput
username, kita mengatur prop onFocus
dengan memanggil method clearValidationErrors
, maka tambahkan function berikut yang berfungsi untuk menghapus error:
clearValidationErrors(){
this.setState({
error: false
})
}
Karena kita membutuhkan beberapa state, diantaranya: username, password, error, isAuthenticated, loading. Maka kita tetapkan nilai defaultnya terlebih dahulu, tambahkan code berikut:
state = {
user: '',
password: '',
error: false,
isAuthenticated: false,
loading: false
}
Pada screen ini, kita tidak membutuhkan sebuah header, maka navigationOptions
akan diset null
:
static navigationOptions = {
header: null
}
Baca Juga: React Native Navigation
Authentication Logic
Izinkan saya untuk beranjak ke tahap authentication logic terlebih dahulu, sedangkan untuk SignUp screen kita skip dulu dan akan dilanjutkan kemudian. Jika kita perhatikan, pada Login.js terdapat code untuk meng-import SplashScreen
, maka buat file SplashScreen.js di dalam folder src/components
kemudian masukkan code berikut:
import React from 'react';
import { View, ActivityIndicator } from 'react-native';
export default function SplashScreen(){
return (
<View style={{ flex: 1, justifyContent: 'center'}}>
<ActivityIndicator
animating={true}
style={[styles.centering, {height: 80}]}
size="large"
/>
</View>
)
}
const styles = {
centering: {
alignItems: 'center',
justifyContent: 'center',
padding: 8
}
}
Tak ada yang perlu dijelaskan dari code di atas, karena hanya sebuah component biasa yang di dalamnya terdapat ActivityIndicator
yang akan memicu efek loading. Langkah berikutnya adalah dengan membuat service API, buka file api.js yang terdapat di dalam folder src/services
, kemudian modifikasi menjadi seperti ini:
import { setListener, pushData, initialize, signup, login } from './firebase';
export const initApi = () => initialize();
export const getMessages = (updaterFn) => setListener('messages', updaterFn);
export const postMessage = (message) => {
if (Boolean(message)) {
pushData('messages', {
incoming: false,
message
})
}
}
export {
login,
signup
}
Pada file firebase.js, tambahkan function login dan signup berikut:
export const login = (email, pass) =>
firebase.auth()
.signInWithEmailAndPassword(email, pass)
export const signup = (email, pass) =>
firebase.auth().createUserWithEmailAndPassword(email, pass);
Penjelasan: Masing-masing dari function diatas menerima value email dan password, dimana akan dikirimkan ke Firebase untuk melakukan otentikasi baik berupa login maupun signup.
Sampai pada tahap ini fitur login telah selesai dan siap digunakan, adapun tampilannya tampak seperti dibawah ini
Karena kita belum memiliki user, maka buat file Signup.js di dalam folder src/screens
, kemudian masukkan code berikut:
import React from 'react';
import { signup } from '../services/api';
import { View, StyleSheet, Image, ScrollView, TextInput, Button, Text, Keyboard, TouchableOpacity } from 'react-native';
import { NavigationActions } from 'react-navigation';
export default class Login extends React.Component {
static navigationOptions = {
header: null
}
state = {
user: '',
password: '',
isAuthenticated: false
}
async submit() {
try {
const response = await signup(this.state.user, this.state.password)
this._user.clear();
this._password.clear();
Keyboard.dismiss();
this.isAuthenticated = true;
this.props.navigation.dispatch(
NavigationActions.reset({
index: 0,
actions: [
NavigationActions.navigate({ routeName: 'home' })
]
})
);
} catch ({ message }) {
this.setState({
error: message
})
}
}
render() {
return (
<View
style={styles.container}>
<Image
style={[ styles.logo ]}
source={require('../assets/img/whatsapplogo.png')} />
<ScrollView style={styles.container}>
<TextInput
ref={(textInput) =>this._user = textInput }
style={styles.inputField}
value={this.state.text}
onChangeText={(user) => this.setState({user})}
onSubmitEditing={(event) => this._password.focus()}
editable={true}
maxLength={40}
multiline={false}
placeholder="Masukkan Email"
/>
<TextInput
ref={(textInput) =>this._password = textInput }
style={styles.inputField}
value={this.state.text}
onChangeText={(password) => this.setState({password})}
onSubmitEditing={(event) => this.submit()}
editable={true}
secureTextEntry={true}
maxLength={40}
multiline={false}
placeholder="Masukkan Password"
/>
{ this.state.error &&
<View style={styles.validationErrors}>
<Text style={styles.error}>{this.state.error}</Text>
</View>
}
<View style={styles.buttonStyle}>
<Button
onPress={() => this.submit()}
title="Daftar" />
</View>
<View style={styles.redirectLink}>
<Text>Sudah punya akun? </Text>
<TouchableOpacity onPress={() =>
this.props.navigation.navigate('login')}>
<Text style={styles.link}>Masuk</Text>
</TouchableOpacity>
</View>
<View style={styles.copyright}>
<Text style={{fontSize: 18, color: '#19B5FE'}}>https://daengweb.id</Text>
</View>
</ScrollView>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'white'
},
logo: {
width: '100%',
height: 200
},
inputField: {
marginTop: 20,
alignSelf: 'center',
height: 55,
width: '80%',
backgroundColor: '#FAFAFA',
borderWidth: 1,
paddingHorizontal: 10,
borderRadius: 10,
borderColor: "#CACACA"
},
redirectLink: {
flex: 1,
flexDirection: 'row',
alignSelf: 'center'
},
link: {
color: 'blue'
},
validationErrors: {
flexDirection: 'row',
justifyContent: 'center',
},
error: {
marginTop: 10,
textAlign: 'center',
color: 'red'
},
buttonStyle: {
marginTop: 15,
flex: 1
},
copyright: {
marginTop: 15,
flex: 1,
alignSelf: 'center'
}
})
Tak ada yang perlu dijelaskan dari code diatas, karena hampir mirip dengan Login.js. Adapun tampilannya tampak seperti ini:
Kesimpulan
Membuat fitur authentication diatas telah mengajari kita banyak hal bagaimana bekerja dengan React Native, sebuah case yang sederhana yang bisa mengasah logika kita untuk mengerti alur dari sebuah fitur yang diinginkan. Maka kunci dari belajar pemrograman adalah Repeat. Ohya, code lengkapnya dapat kamu download di Github. Semoga bermanfaat.
Comments