Create a simple React app (TypeScript) with Login / Register pages using create-react-app

Prabhashi Meddegoda
5 min readSep 15, 2023

--

This is the first part of a series to implement the authentication and authorization process for a full stack application.

Here, we’ll create a React app using TypeScript and use MUI to create the UI, and React Router V6 for client-side routing. I’m using create-react-app to create the React app.

1. Creating the React app

Open the terminal and cd to the folder where you want to create the app. Run below command. This will create a React app named “frontend” in TypeScript.

npx create-react-app frontend --template typescript

Open the application in VS Code. Open the terminal in VS Code and run below command.

npm start

Your app will be served in http://localhost:3000/

We don’t need some of the files created under our application folder. Remove these files (App.css, App.test.tsx, index.css, logo.svg) and your file structure should be as below.

Initial folder structure

Remove the index.css import from index.tsx file. Update the App.tsx file as below.

Initial App.tsx file

Now we can continue with the implementation of the app.

2. Client-side routing using React Router

Run the following command to install the package.

npm i react-router-dom

Create 3 files under a pages folder as below, with basic implementation.

Folder structure for pages

Import BrowserRouter in index.tsx file and wrap App component with it as below.

BrowserRouter usage in index.tsx

In App.tsx file, import the components created for the pages and implement the routing as below.

Routing in App.tsx

Now if you restart the app (npm start), you’ll be able to view each page by typing the links in the address bar.

Basic frontend app in localhost

3. UI implementation (Login / Register)

I’m using MUI free templates for Login and Register pages, with a few updates.

First install mui, its dependencies and icons using below command.

npm i @mui/material @emotion/react @emotion/styled @mui/icons-material

Add below code to Login.tsx to implement the UI and to handle input field data.

import { LockOutlined } from "@mui/icons-material";
import {
Container,
CssBaseline,
Box,
Avatar,
Typography,
TextField,
Button,
Grid,
} from "@mui/material";
import { useState } from "react";
import { Link } from "react-router-dom";

const Login = () => {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");

const handleLogin = () => {};

return (
<>
<Container maxWidth="xs">
<CssBaseline />
<Box
sx={{
mt: 20,
display: "flex",
flexDirection: "column",
alignItems: "center",
}}
>
<Avatar sx={{ m: 1, bgcolor: "primary.light" }}>
<LockOutlined />
</Avatar>
<Typography variant="h5">Login</Typography>
<Box sx={{ mt: 1 }}>
<TextField
margin="normal"
required
fullWidth
id="email"
label="Email Address"
name="email"
autoFocus
value={email}
onChange={(e) => setEmail(e.target.value)}
/>

<TextField
margin="normal"
required
fullWidth
id="password"
name="password"
label="Password"
type="password"
value={password}
onChange={(e) => {
setPassword(e.target.value);
}}
/>

<Button
fullWidth
variant="contained"
sx={{ mt: 3, mb: 2 }}
onClick={handleLogin}
>
Login
</Button>
<Grid container justifyContent={"flex-end"}>
<Grid item>
<Link to="/register">Don't have an account? Register</Link>
</Grid>
</Grid>
</Box>
</Box>
</Container>
</>
);
};

export default Login;

Add below code to Register.tsx to implement the UI and to handle input field data.

import {
Avatar,
Box,
Button,
Container,
CssBaseline,
Grid,
TextField,
Typography,
} from "@mui/material";
import { LockOutlined } from "@mui/icons-material";
import { useState } from "react";
import { Link } from "react-router-dom";

const Register = () => {
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");

const handleRegister = async () => {};

return (
<>
<Container maxWidth="xs">
<CssBaseline />
<Box
sx={{
mt: 20,
display: "flex",
flexDirection: "column",
alignItems: "center",
}}
>
<Avatar sx={{ m: 1, bgcolor: "primary.light" }}>
<LockOutlined />
</Avatar>
<Typography variant="h5">Register</Typography>
<Box sx={{ mt: 3 }}>
<Grid container spacing={2}>
<Grid item xs={12}>
<TextField
name="name"
required
fullWidth
id="name"
label="Name"
autoFocus
value={name}
onChange={(e) => setName(e.target.value)}
/>
</Grid>

<Grid item xs={12}>
<TextField
required
fullWidth
id="email"
label="Email Address"
name="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
</Grid>
<Grid item xs={12}>
<TextField
required
fullWidth
name="password"
label="Password"
type="password"
id="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
</Grid>
</Grid>
<Button
fullWidth
variant="contained"
sx={{ mt: 3, mb: 2 }}
onClick={handleRegister}
>
Register
</Button>
<Grid container justifyContent="flex-end">
<Grid item>
<Link to="/login">Already have an account? Login</Link>
</Grid>
</Grid>
</Box>
</Box>
</Container>
</>
);
};

export default Register;

The UIs will be updated as below.

Login and Register pages

When we click Login / Register buttons, handleLogin() / handleRegister() functions will be called. We haven’t included anything inside those functions yet.

We have to validate the form fields and show an error message if any validation fails. If the validation is successful, we have to initiate an API request to the backend, in order to handle the functionalities.

Follow me and stay tuned! If you have any questions, let me know in the comments!

Next Steps

We’ll use Redux Toolkit for the state management of the application, and Axios to initiate the API requests (login, register, logout, profile).

Next we’ll handle error/success message alerts in a centralized way (using Redux Toolkit and MUI for the message UI).

After that we’ll update the frontend code with redirects and protected routes based on whether the user is logged in or not (authenticated or not).

We’ll implement the backend using Express with TypeScript, and use MongoDB for the database.

Finally, we’ll handle authorization for the frontend and backend applications, using Role Based Access Control.

Then we’ll continue to add more features to the application.

--

--