This post is also available in:
English
Hallo apa kabar teman semuanya, kali ini kita akan membahas login dan register kembali. Akan tetapi kali ini kita akan membuat menggunakan TypeScript.
TypeScript
TypeScript merupakan salah satu bahasa pemrograman yang paling banyak digunakan.
Bahasa pemrograman ini dirancang oleh Anders Hejlsberg dari Microsoft, yang juga desainer dari bahasa pemrograman C#. Versi pertama TypeScript diperkenalkan tahun 2012.
Selain bahasa pemrograman, TypeScript juga sebuah tools. TypeScript merangkum bahasa pemrograman yag telah ada dari JavaScript. Dengan kata lain, TypeScript adalah JavaScript dengan beberapa fitur tambahan.TypeScript menggunakan dua modul, yaitu internal dan eksternal.
Modul internal TypeScript mirip dengan namespace seperti yang tersedia di C#. Ini memungkinkan penetapan simbol (variabel, fungsi, kelas) di luar cakupan global.
Deklarasi modul internal dapat dipecah menjadi beberapa file. Ini mendorong tim pengembangan untuk memiliki proyek yang terstruktur dengan baik dengan file kecil tujuan tunggal.
Sementara itu, modul eksternal adalah cara TypeScript untuk mendefinisikan modul yang dimuat secara asinkron baik untuk sistem pemuatan modul node.js (commonjs) atau require.js (AMD).
TypeScript juga menggunakan modul untuk mendeklarasikan API yang diekspos oleh pihak ketiga.
Itu dilakukan melalui apa yang disebut ” ambien modul internal atau eksternal,” yang hanya berisi kode dan interface.
Cara ini dimungkinkan untuk memberikan level yang sama dari IDE/type checker dukungan untuk kode yang tersedia dalam JavaScript murni seolah-olah itu ditulis dalam TypeScript. Deklarasi ambient seperti itu disimpan dalam file “.d.ts”.
Kalian dapat mempelajari tutorial yang lainnya:
REST API Login dan Register Node.js dengan JWT
Format Number Otomatis Dengan JavaScript Semua Negara
Tutorial JavaScript #1 : Pengenalan Javascript
What is JWT or JSON Web Token?
JSON Web Token adalah standar tingkat Internet modern untuk menghasilkan data dengan tanda tangan sukarela dan enkripsi sukarela yang muatannya membawa JSON yang menyatakan sejumlah klaim. Token telah ditandatangani baik dengan menggunakan rahasia pribadi atau kunci publik/pribadi.
Implementasi
- Buat project baru menggunakan React TypeScript.
npx create-react-app auth-typescript --template typescript

- Buka Direktori Aplikasi React Typescript Anda dan instal paket bootstrap, axios, react-hook-form, react-toastify & react-router-dom dengan perintah berikut:
npm install axios bootstrap react-router-dom@5.2.0 react-hook-form react-toastify
- Di file App.tsx Anda, hapus semua kode dan rekatkan yang berikut ini. Pada dasarnya, apa yang kita coba lakukan untuk menambahkan fungsionalitas react-router-dom untuk merutekan ke halaman dengan tautan yang berbeda-beda:
import React from "react";
import "bootstrap/dist/css/bootstrap.min.css";
import "bootstrap/dist/js/bootstrap.bundle.min.js";
import SignUp from "./Components/SignUp";
import Login from "./Components/Login";
import PrivateRoute from "./Auth/PrivateRoute";
import Home from "./Components/Home";
import {BrowserRouter, Route, Switch} from 'react-router-dom';
function App() {
return (
<BrowserRouter>
<Switch>
<PrivateRoute exact path="/login" component={Login}/>
<Route exact path="/register" component={SignUp} />
</Switch>
</BrowserRouter>
);
}
export default App;
- Sekarang kita akan membuat rute untuk aplikasi kita. Buat folder bernama “Auth” dan di bawah folder ini buat file baru yang dikenal sebagai file PrivateRoute.tsx, salin semua kode dan tempel berikut ini, pada dasarnya apa yang kami coba lakukan di sini adalah kami mengeluarkan Token JWT kami dari Penyimpanan lokal. Dan cek jika kita tidak memiliki token JWT di LocalStorage kita maka kita akan masuk ke rute Login, jika tidak ada token maka akan tetap berada di homepage.
import React from "react";
import { Redirect, Route } from "react-router-dom";
const PrivateRoute = (props) => {
const token = localStorage.getItem("auth");
return <>{token ? <Route {...props} /> : <Redirect to="/login" />}</>;
};
export default PrivateRoute;
- Sekarang kita akan membuat UI untuk ini. Pertama buka folder src, lalu di dalam folder src buat folder baru bernama “Komponen”.
Dan di dalam folder komponen buat 3 file sebagai:
Login.tsx
SignUp.tsx
Home.tsx
home.css

Sebelum kami melanjutkan lebih jauh, pastikan Anda memiliki API Node Otentikasi JWT Anda sendiri yang menyediakan Token JWT. Karena kami menggunakan yang dibuat di mesin lokal kami. Silahkan ubah kode URL http://localhost:4000 sesuai dengan kode URL API Anda.
Login.tsx
import React, { FC } from "react";
import { Link } from "react-router-dom";
import { useForm } from "react-hook-form";
import axios from "axios";
import { ToastContainer, toast, Flip } from "react-toastify";
import "react-toastify/dist/ReactToastify.min.css";
import { RouteComponentProps } from "react-router";
type SomeComponentProps = RouteComponentProps;
const Login: FC<SomeComponentProps> = ({ history }): JSX.Element => {
const {
register,
handleSubmit,
formState: { errors },
} = useForm();
const login = (data: any) => {
let params = {
email: data.email,
password: data.password,
};
axios
.post("http://localhost:3000/api/login", params)
.then(function (response) {
// IF EMAIL ALREADY EXISTS
if (response.data.success === false) {
toast.error(response.data.error, {
position: "top-right",
autoClose: 3000,
hideProgressBar: true,
closeOnClick: true,
pauseOnHover: true,
draggable: false,
progress: 0,
toastId: "my_toast",
});
} else {
toast.success(response.data.message, {
position: "top-right",
autoClose: 3000,
hideProgressBar: true,
closeOnClick: true,
pauseOnHover: true,
draggable: false,
progress: 0,
toastId: "my_toast",
});
localStorage.setItem("auth", response.data.token);
setTimeout(() => {
history.push("/");
}, 3000);
}
})
.catch(function (error) {
console.log(error);
});
};
return (
<>
<div className="container">
<div
className="row d-flex justify-content-center align-items-center"
style={{ height: "100vh" }}
>
<div className="card mb-3" style={{ maxWidth: "320px" }}>
<div className="col-md-12">
<div className="card-body">
<h3 className="card-title text-center text-secondary mt-3">
Login Form
</h3>
<form autoComplete="off" onSubmit={handleSubmit(login)}>
<div className="mb-3 mt-4">
<label className="form-label">Email</label>
<input
type="email"
className="form-control shadow-none"
id="exampleFormControlInput1"
{...register("email", { required: "Email is required!" })}
/>
{errors.email && (
<p className="text-danger" style={{ fontSize: 14 }}>
{errors.email.message}
</p>
)}
</div>
<div className="mb-3">
<label className="form-label">Password</label>
<input
type="password"
className="form-control shadow-none"
id="exampleFormControlInput2"
{...register("password", {
required: "Password is required!",
})}
/>
{errors.password && (
<p className="text-danger" style={{ fontSize: 14 }}>
{errors.password.message}
</p>
)}
</div>
<div className="text-center mt-4 ">
<button
className="btn btn-outline-primary text-center shadow-none mb-3"
type="submit"
>
Submit
</button>
<p className="card-text pb-2">
Have an Account?{" "}
<Link style={{ textDecoration: "none" }} to={"/register"}>
Sign Up
</Link>
</p>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<ToastContainer
position="top-right"
autoClose={5000}
hideProgressBar
closeOnClick
rtl={false}
pauseOnFocusLoss={false}
draggable={false}
pauseOnHover
limit={1}
transition={Flip}
/>
</>
);
};
export default Login;
SignUp.tsx
import React, { FC } from "react";
import { Link, RouteComponentProps } from "react-router-dom";
import { useForm } from "react-hook-form";
import axios from "axios";
import { ToastContainer, toast, Flip } from "react-toastify";
import "react-toastify/dist/ReactToastify.min.css";
type SomeComponentProps = RouteComponentProps;
const SignUp: FC<SomeComponentProps> = ({ history }) => {
const {
register,
handleSubmit,
watch,
reset,
formState: { errors },
} = useForm();
const submitData = (data: any) => {
let params = {
firstname: data.firstname,
lastname: data.lastname,
email: data.email,
password: data.password,
confirmpassword: data.cpassword,
};
console.log(data);
axios
.post("http://localhost:3000/api/signup", params)
.then(function (response) {
toast.success(response.data.message, {
position: "top-right",
autoClose: 3000,
hideProgressBar: true,
closeOnClick: true,
pauseOnHover: true,
draggable: false,
progress: 0,
toastId: "my_toast",
});
reset();
setTimeout(() => {
history.push("/login");
}, 3000);
})
.catch(function (error) {
console.log(error);
});
};
return (
<>
<div className="container">
<div
className="row d-flex justify-content-center align-items-center"
style={{ height: "100vh" }}
>
<div className="card mb-3 mt-3 rounded" style={{ maxWidth: "500px" }}>
<div className="col-md-12">
<div className="card-body">
<h3 className="card-title text-center text-secondary mt-3 mb-3">
Sign Up Form
</h3>
<form
className="row"
autoComplete="off"
onSubmit={handleSubmit(submitData)}
>
<div className="col-md-6">
<div className="">
<label className="form-label">Firstname</label>
<input
type="text"
className="form-control form-control-sm"
id="exampleFormControlInput1"
{...register("firstname", {
required: "Firstname is required!",
})}
/>
{errors.firstname && (
<p className="text-danger" style={{ fontSize: 14 }}>
{errors.firstname.message}
</p>
)}
</div>
</div>
<div className="col-md-6">
<div className="">
<label className="form-label">Lastname</label>
<input
type="text"
className="form-control form-control-sm"
id="exampleFormControlInput2"
{...register("lastname", {
required: "Lastname is required!",
})}
/>
{errors.lastname && (
<p className="text-danger" style={{ fontSize: 14 }}>
{errors.lastname.message}
</p>
)}
</div>
</div>
<div className="">
<label className="form-label">Email</label>
<input
type="email"
className="form-control form-control-sm"
id="exampleFormControlInput3"
{...register("email", { required: "Email is required!" })}
/>
{errors.email && (
<p className="text-danger" style={{ fontSize: 14 }}>
{errors.email.message}
</p>
)}
</div>
<div className="">
<label className="form-label">Password</label>
<input
type="password"
className="form-control form-control-sm"
id="exampleFormControlInput5"
{...register("password", {
required: "Password is required!",
})}
/>
{errors.password && (
<p className="text-danger" style={{ fontSize: 14 }}>
{errors.password.message}
</p>
)}
</div>
<div>
<label className="form-label">Confirm Password</label>
<input
type="password"
className="form-control form-control-sm"
id="exampleFormControlInput6"
{...register("cpassword", {
required: "Confirm Password is required",
validate: (value) =>
value === watch("password") ||
"Passwords don't match.",
})}
/>
{errors.cpassword && (
<p className="text-danger" style={{ fontSize: 14 }}>
{errors.cpassword.message}
</p>
)}
</div>
<div className="text-center mt-4 ">
<button
className="btn btn-outline-primary text-center shadow-none mb-3"
type="submit"
>
Submit
</button>
<p className="card-text">
Already have an account?{" "}
<Link style={{ textDecoration: "none" }} to={"/login"}>
Log In
</Link>
</p>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<ToastContainer
position="top-right"
autoClose={5000}
hideProgressBar
closeOnClick
rtl={false}
pauseOnFocusLoss={false}
draggable={false}
pauseOnHover
limit={1}
transition={Flip}
/>
</>
);
};
export default SignUp;
Home.tsx
import React, { FC } from "react";
import { RouteComponentProps } from "react-router-dom";
import "./home.css";
type SomeComponentProps = RouteComponentProps;
const Home: FC<SomeComponentProps> = ({ history }) => {
const logout = () => {
localStorage.clear();
history.push("/login");
};
return (
<>
<div
style={{
display: "flex",
justifyContent: "space-between",
paddingLeft: 50,
paddingRight: 50,
}}
>
<div>
<h3 className="m-3">Home</h3>
</div>
<div>
<button type="submit" className="buttons" onClick={logout}>
Logout
</button>
</div>
</div>
<div className="container">
<div
className="row d-flex justify-content-center align-items-center text-center"
style={{ height: "100vh" }}
>
<p className="muted display-6">Hello User👋</p>
</div>
</div>
</>
);
};
export default Home;
home.css
.buttons
{
color: white;
background: cornflowerblue;
padding: 10px 40px;
margin: 10px;
border: none;
border-radius: 30px;
cursor: pointer;
}
- Now execute the code by following command:
npm start
Demikian tutorial kali ini yang bisa saya sampaikan, semoga bermanfaat.
Terimakasih…
Sumber :