I am trying to prepare a faulty record app but after I successfully log in and direct to dashboard. Pressing F5 gives me "Hydration failed because the server rendered HTML didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used" error. I have tried if(windows !== undefined)
and other options but nothing seems to work for me.
App.jsx
import { useState, useEffect } from "react";
import { useNavigate } from "react-router-dom";
export default function App() {
const navigate = useNavigate();
const getStoredUsers = () => {
try {
return JSON.parse(localStorage.getItem("users")) || [];
} catch {
return [];
}
};
const [users, setUsers] = useState(getStoredUsers);
const [loginData, setLoginData] = useState({ username: "", password: "" });
const [signupData, setSignupData] = useState({ username: "", password: "" });
const [error, setError] = useState("");
const [isSignupOpen, setIsSignupOpen] = useState(false);
useEffect(() => {
localStorage.setItem("users", JSON.stringify(users));
}, [users]);
const handleLogin = (e) => {
e.preventDefault();
const user = users.find(
(u) =>
u.username === loginData.username && u.password === loginData.password
);
if (user) {
localStorage.setItem("loggedInUser", JSON.stringify(user));
navigate("/dashboard");
} else {
setError("Invalid credentials");
}
};
const handleSignup = (e) => {
e.preventDefault();
if (users.some((u) => u.username === signupData.username)) {
setError("Username already exists");
return;
}
setUsers([...users, signupData]);
setIsSignupOpen(false);
setSignupData({ username: "", password: "" });
};
return (
<div className="flex items-center justify-center min-h-screen bg-gray-100">
<div className="bg-white p-8 rounded shadow-md w-96">
<h2 className="text-2xl font-bold mb-4">Login</h2>
{error && <p className="text-red-500">{error}</p>}
<form onSubmit={handleLogin}>
<input
type="text"
placeholder="Username"
className="w-full p-2 border rounded mb-2"
onChange={(e) =>
setLoginData({ ...loginData, username: e.target.value })
}
/>
<input
type="password"
placeholder="Password"
className="w-full p-2 border rounded mb-2"
onChange={(e) =>
setLoginData({ ...loginData, password: e.target.value })
}
/>
<button
className="w-full bg-blue-500 text-white p-2 rounded"
type="submit"
>
Login
</button>
</form>
<p className="mt-4 text-center">
Don't have an account?{" "}
<button
className="text-blue-500"
onClick={() => setIsSignupOpen(true)}
>
Sign Up
</button>
</p>
</div>
{isSignupOpen && (
<div className="fixed inset-0 flex items-center justify-center bg-black bg-opacity-50">
<div className="bg-white p-6 rounded shadow-md w-96">
<h2 className="text-2xl font-bold mb-4">Sign Up</h2>
{error && <p className="text-red-500">{error}</p>}
<form onSubmit={handleSignup}>
<input
type="text"
placeholder="Username"
className="w-full p-2 border rounded mb-2"
onChange={(e) =>
setSignupData({ ...signupData, username: e.target.value })
}
/>
<input
type="password"
placeholder="Password"
className="w-full p-2 border rounded mb-2"
onChange={(e) =>
setSignupData({ ...signupData, password: e.target.value })
}
/>
<button
className="w-full bg-green-500 text-white p-2 rounded"
type="submit"
>
Sign Up
</button>
</form>
<button
className="mt-4 text-red-500 w-full"
onClick={() => setIsSignupOpen(false)}
>
Cancel
</button>
</div>
</div>
)}
</div>
);
}
Dashboard.jsx
import { useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";
export default function Dashboard() {
const navigate = useNavigate();
const [loggedInUser, setLoggedInUser] = useState(null);
const [isMounted, setIsMounted] = useState(false);
useEffect(() => {
setIsMounted(true);
const storedUser = localStorage.getItem("loggedInUser");
if (storedUser) {
try {
const parsedUser = JSON.parse(storedUser);
setLoggedInUser(parsedUser?.username || "Guest");
} catch (error) {
console.error("Error parsing logged-in user:", error);
navigate("/");
}
} else {
navigate("/");
}
}, [navigate]);
if (!isMounted) {
return <div>Loading...</div>;
}
return (
<div className="p-6 bg-gray-100 min-h-screen">
<div className="flex justify-between items-center mb-4">
<h1 className="text-2xl font-bold">FAULTY RECORD SYSTEM</h1>
<div className="flex items-center space-x-4">
<span className="font-semibold">{loggedInUser}</span>
<button
onClick={() => {
localStorage.removeItem("loggedInUser");
navigate("/");
}}
className="bg-red-500 text-white px-4 py-2 rounded"
>
Log Off.
</button>
</div>
</div>
</div>
);
}