I'm using firebase auth for verifying my email when recovering password. I want to implement the same idea where the user will receive a confirm registration link via email upon signing up. However, I'm new to ReactJS and I'm hoping for someone who can share their knowledge that will answer my inquiry.
See codes below: App.js
import React from "react"
import Signup from "./Signup"
import { Container } from "react-bootstrap"
import { AuthProvider } from "../contexts/AuthContext"
import { BrowserRouter as Router, Switch, Route } from "react-router-dom"
import Dashboard from "./Dashboard"
import Login from "./Login"
import PrivateRoute from "./PrivateRoute"
import ForgotPassword from "./ForgotPassword"
function App() {
return (
<Container
className="d-flex align-items-center justify-content-center"
style={{ minHeight: "100vh" }}
>
<div className="w-100" style={{ maxWidth: "400px" }}>
<Router>
<AuthProvider>
<Switch>
<PrivateRoute exact path="/" component={Dashboard} />
<Route path="/signup" component={Signup} />
<Route path="/login" component={Login} />
<Route path="/forgot-password" component={ForgotPassword} />
</Switch>
</AuthProvider>
</Router>
</div>
</Container>
)
}
export default App
Dashboard.js
import React, { useState } from "react"
import { Card, Button, Alert } from "react-bootstrap"
import { useAuth } from "../contexts/AuthContext"
import { Link, useHistory } from "react-router-dom"
export default function Dashboard() {
const [error, setError] = useState("")
const { currentUser, logout } = useAuth()
const history = useHistory()
async function handleLogout() {
setError("")
try {
await logout()
history.push("/login")
} catch {
setError("Failed to log out")
}
}
return (
<>
<div className="w-100 text-center mt-2">
<h2>Login successfully</h2>
<Button variant="link" onClick={handleLogout}>
Log Out
</Button>
</div>
</>
)
}
ForgotPassword.js
import React, { useRef, useState } from "react"
import { Form, Button, Card, Alert } from "react-bootstrap"
import { useAuth } from "../contexts/AuthContext"
import { Link } from "react-router-dom"
export default function ForgotPassword() {
const emailRef = useRef()
const { resetPassword } = useAuth()
const [error, setError] = useState("")
const [message, setMessage] = useState("")
const [loading, setLoading] = useState(false)
async function handleSubmit(e) {
e.preventDefault()
try {
setMessage("")
setError("")
setLoading(true)
await resetPassword(emailRef.current.value)
setMessage("Check your inbox for further instructions")
} catch {
setError("Failed to reset password")
}
setLoading(false)
}
return (
<>
<Card>
<Card.Body>
<h2 className="text-center mb-4">Password Reset</h2>
{error && <Alert variant="danger">{error}</Alert>}
{message && <Alert variant="success">{message}</Alert>}
<Form onSubmit={handleSubmit}>
<Form.Group id="email">
<Form.Label>Email</Form.Label>
<Form.Control type="email" ref={emailRef} required />
</Form.Group>
<Button disabled={loading} className="w-100" type="submit">
Reset Password
</Button>
</Form>
<div className="w-100 text-center mt-3">
<Link to="/login">Login</Link>
</div>
</Card.Body>
</Card>
<div className="w-100 text-center mt-2">
Need an account? <Link to="/signup">Sign Up</Link>
</div>
</>
)
}
Login.js
import React, { useRef, useState } from "react"
import { Form, Button, Card, Alert } from "react-bootstrap"
import { useAuth } from "../contexts/AuthContext"
import { Link, useHistory } from "react-router-dom"
export default function Login() {
const emailRef = useRef()
const passwordRef = useRef()
const { login } = useAuth()
const { sendEmailVerification} = useAuth()
const [error, setError] = useState("")
const [loading, setLoading] = useState(false)
const history = useHistory()
async function handleSubmit(e) {
e.preventDefault()
try {
setError("")
setLoading(true)
await login(emailRef.current.value, passwordRef.current.value)
await sendEmailVerification(emailRef.current.value)
history.push("/")
} catch {
setError("Failed to log in")
}
setLoading(false)
}
return (
<>
<Card>
<Card.Body>
<h2 className="text-center mb-4">Log In</h2>
{error && <Alert variant="danger">{error}</Alert>}
<Form onSubmit={handleSubmit}>
<Form.Group id="email">
<Form.Label>Email</Form.Label>
<Form.Control type="email" ref={emailRef} required placeholder="Enter your email"/>
</Form.Group>
<Form.Group id="password">
<Form.Label>Password</Form.Label>
<Form.Control type="password" ref={passwordRef} required placeholder="Enter your email"/>
</Form.Group>
<Button disabled={loading} className="w-100" type="submit">
Log In
</Button>
</Form>
<div className="w-100 text-center mt-3">
<Link to="/forgot-password">Forgot Password?</Link>
</div>
</Card.Body>
</Card>
<div className="w-100 text-center mt-2">
Need an account? <Link to="/signup">Sign Up</Link>
</div>
</>
)
}
PrivateRoute.js
import React from "react"
import { Route, Redirect } from "react-router-dom"
import { useAuth } from "../contexts/AuthContext"
export default function PrivateRoute({ component: Component, ...rest }) {
const { currentUser } = useAuth()
return (
<Route
{...rest}
render={props => {
return currentUser ? <Component {...props} /> : <Redirect to="/login" />
}}
></Route>
)
}
Signup.js
import React, { useRef, useState } from "react"
import { Form, Button, Card, Alert } from "react-bootstrap"
import { useAuth } from "../contexts/AuthContext"
import { Link, useHistory } from "react-router-dom"
export default function Signup() {
const emailRef = useRef()
const passwordRef = useRef()
const passwordConfirmRef = useRef()
const { signup } = useAuth()
const [error, setError] = useState("")
const [loading, setLoading] = useState(false)
const history = useHistory()
async function handleSubmit(e) {
e.preventDefault()
if (!(/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/).test(emailRef.current.value)) {
return setError("Invalid Email")
}
else if (!(/^.{8,}$/).test(passwordRef.current.value)) {
return setError("Invalid Password")
}
else if (passwordRef.current.value !== passwordConfirmRef.current.value) {
return setError("Passwords do not match")
}
setError("")
try {
setError("")
setLoading(true)
await signup(emailRef.current.value, passwordRef.current.value)
history.push("/")
} catch {
setError("Failed to create an account")
}
setLoading(false)
}
return (
<>
<Card>
<Card.Body>
<h2 className="text-center mb-4">Sign Up</h2>
{error && <Alert variant="danger">{error}</Alert>}
<Form onSubmit={handleSubmit}>
<Form.Group id="email">
<Form.Label>Email</Form.Label>
<Form.Control type="email" ref={emailRef} required placeholder="Enter your email"/>
</Form.Group>
<Form.Group id="password">
<Form.Label>Password</Form.Label>
<Form.Control type="password" ref={passwordRef} required placeholder="Must be atleast 8 characters long"/>
</Form.Group>
<Form.Group id="password-confirm">
<Form.Label>Confirm Password</Form.Label>
<Form.Control type="password" ref={passwordConfirmRef} required placeholder="Reenter Password"/>
</Form.Group>
<Button disabled={loading} className="w-100" type="submit">
Sign Up
</Button>
</Form>
</Card.Body>
</Card>
<div className="w-100 text-center mt-2">
Already have an account? <Link to="/login">Log In</Link>
</div>
</>
)
}
AuthContext.js
import React, { useContext, useState, useEffect } from "react"
import { auth } from "../firebase"
const AuthContext = React.createContext()
export function useAuth() {
return useContext(AuthContext)
}
export function AuthProvider({ children }) {
const [currentUser, setCurrentUser] = useState()
const [loading, setLoading] = useState(true)
function signup(email, password) {
return auth.createUserWithEmailAndPassword(email, password)
}
function login(email, password) {
return auth.signInWithEmailAndPassword(email, password)
}
function logout() {
return auth.signOut()
}
function resetPassword(email) {
return auth.sendPasswordResetEmail(email)
}
function updateEmail(email) {
return currentUser.updateEmail(email)
}
function updatePassword(password) {
return currentUser.updatePassword(password)
}
useEffect(() => {
const unsubscribe = auth.onAuthStateChanged(user => {
setCurrentUser(user)
setLoading(false)
})
return unsubscribe
}, [])
const value = {
currentUser,
login,
signup,
logout,
resetPassword,
updateEmail,
updatePassword
}
return (
<AuthContext.Provider value={value}>
{!loading && children}
</AuthContext.Provider>
)
}
Additional info regarding the file directory below: enter image description here