This particular things seems happening when i run these codes
AuthContext.jsx:
// context is a state management tool for passing props
import { createContext, useReducer } from "react";
// initial state
const initialState = {
user: null, //user details
role: null,
token: null,
};
// create a common context with initial state
export const authContext = createContext(initialState);
// reducer function
const authReducer = (state, action) => {
// action types
switch (action.type) {
case "LOGIN_START":
// login starting
return {
user: null,
role: null,
token: null,
};
// login success
case "LOGIN_SUCCESS":
return {
user: action.payload.user, //data will be recieved as a payload
role: action.payload.role,
token: action.payload.token,
};
// logout state
case "LOGOUT": //data is set to null again
return {
user: null,
role: null,
token: null,
};
// default
default:
return state;
}
};
// export provider
export const AuthContextProvider = ({ children }) => {
//all children can access the provider
const [state, dispatch] = useReducer(authReducer, initialState)
return (
<authContext.Provider
value={{
user: state.user,
token: state.token,
role: state.role,
dispatch,
}}
>
{children}
</authContext.Provider>
);
};
Login.jsx:
import { useState, useContext } from "react";
import avatar_img from "../assets/images/patient-avatar.png";
import { Link } from "react-router-dom";
import { useNavigate } from "react-router-dom";
import { toast } from "react-toastify";
import { authContext } from "../context/AuthContext.jsx";
export default function Login() {
const [loading, setLoading] = useState(false);
const navigate = useNavigate();
const { dispatch } = useContext(authContext);
const [formData, setFormData] = useState({
// login function parameters
email: "",
password: "",
});
const handleChange = (e) => {
setFormData({ ...formData, [e.target.name]: e.target.value });
};
const handleSubmit = async (e) => {
e.preventDefault();
setLoading(true);
try {
const res = await fetch("http://localhost:8000/api/v1/auth/login", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(formData),
});
const result = await res.json();
if (!res.ok) {
throw new Error(result.message || "Something went wrong");
}
dispatch({
type: "LOGIN_SUCCESS",
payload: {
user: result.data,
token: result.token,
role: result.role, //result is from the res.json()
},
});
console.log(result,"login data");
toast.success(result.message);
setLoading(false);
navigate("/");
} catch (error) {
toast.error("Registration failed");
setLoading(false);
console.log("Error in registration", error.message);
}
};
return (
<section className="p-3 lg:p-1">
<div className="w-full max-w-[570px] mx-auto rounded-md shadow-xl p-3 md:p-10">
<div className="flex justify-center gap-[20px] items-center">
<img
src={avatar_img}
className="w-[40px] h-auto rounded-full"
alt=""
/>
<h2 className="text-3xl text-center font-semibold text-irisBlueColor">
Login
</h2>
</div>
{/* login form */}
<form action="" className="py-4 md:py-0" onSubmit={handleSubmit}>
<div className="mb-5">
<input
type="email"
name="email"
id="email"
placeholder="[email protected]"
className="placeholder:text-gray-400 w-full px-4 py-3 border-b border-solid border-teal-500 focus:outline-none focus:border-b-green-500 text-[15px] leading-7 cursor-text "
value={formData.email} //setting the value as email
onChange={handleChange}
required
/>
</div>
<div className="mb-5">
<input
type="password"
name="password"
id="password"
placeholder="**********"
className="placeholder:text-gray-400 w-full px-4 py-3 border-b border-solid border-teal-500 focus:outline-none focus:border-b-green-500 text-[15px] leading-7 cursor-text "
value={formData.password} //setting the value as email
onChange={handleChange}
required
/>
</div>
<div className="flex items-center justify-between">
<button className="btn mt-0" type="submit">
Login
</button>
{/* link for register */}
<p className=" text-textColor text-center">
Don't have an account ,
<Link
to="/register"
className=" text-irisBlueColor hover:text-primaryColor"
>
create one
</Link>
</p>
</div>
{/* google auth */}
<button className="w-full outline-teal-500 rounded-2xl mt-5 font-semibold bg-primaryColor text-white p-3">
continue with google
</button>
</form>
</div>
</section>
);
}
Header.jsx:
import logo from "../../assets/images/logo.png";
import userImg from "../../assets/images/avatar-icon.png";
import { useEffect, useRef, useContext } from "react";
import { CgMenuMotion } from "react-icons/cg";
import { NavLink, Link } from "react-router-dom";
import { authContext } from "../../context/AuthContext";
const navLinks = [
{ path: "/", display: "Home" },
{ path: "/doctors", display: "Find a Doctor" },
{ path: "/services", display: "Services" },
{ path: "/contact", display: "Contact" },
];
export default function Header() {
const { user, role, token } = useContext(authContext);
console.log(user); // Verify the user object here
const headerRef = useRef(null);
const menuRef = useRef(null);
const handleStickyHeader = () => {
window.addEventListener("scroll", () => {
if (document.body.scrollTop > 80 || document.documentElement.scrollTop > 80) {
headerRef.current.classList.add("sticky__header");
} else {
headerRef.current.classList.remove("sticky__header");
}
});
};
useEffect(() => {
handleStickyHeader();
}, []);
const toggleMenu = () => {
menuRef.current.classList.toggle("show__menu");
};
return (
<header className="header flex items-center" ref={headerRef}>
<div className="container">
<div className="flex items-center justify-between">
<div>
<img src={logo} alt="MEDICARE logo" />
</div>
<div className="navigation" ref={menuRef} onClick={toggleMenu}>
<ul className="menu flex items-center gap-[2.7rem]">
{navLinks.map((link, index) => (
<li key={index}>
<NavLink
to={link.path}
className={(navClass) =>
navClass.isActive
? "text-primaryColor text-[16px] leading-7 font-[600]"
: "text-textColor text-[16px] leading-7 font-[500] hover:text-primaryColor"
}
>
{link.display}
</NavLink>
</li>
))}
</ul>
</div>
<div className="flex items-center gap-4">
{token && user ? (
<div>
<Link to="/">
<figure className="w-[35px] h-[35px] rounded-full cursor-pointer">
<img src={userImg} alt="" className="w-full rounded-full" />
</figure>
</Link>
<h1>{user?.name}</h1>
</div>
) : (
<Link to="/login">
<button className="bg-primaryColor py-2 px-7 items-center text-white font-[600] h-[44px] flex justify-center rounded-[50px]">
Login
</button>
</Link>
)}
<span className="md:hidden" onClick={toggleMenu}>
<CgMenuMotion className="h-6 w-6 cursor-pointer" />
</span>
</div>
</div>
</div>
</header>
);
}
main.jsx:
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App.jsx";
import "./index.css";
import { BrowserRouter } from "react-router-dom";
import { ToastContainer } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
import { AuthContextProvider } from "./context/AuthContext.jsx";
ReactDOM.createRoot(document.getElementById("root")).render(
<React.StrictMode>
<BrowserRouter>
<AuthContextProvider>
<ToastContainer
theme="dark"
position="top-right"
autoClose={300}
closeOnClick
pauseOnFocusLoss={false}
/>
<App />
</AuthContextProvider>
</BrowserRouter>
</React.StrictMode>
);
the problem is the code console logs role and token but it gives me user as undefined
here is the screen shot of it : console output image for Header.jsx:
the role and token are accessible but the user is undefined in Header.jsx
Edits:: This is the screen shot of the console of the window after login img1
result.data, on line 38 ofLogin.jsxmight benull. Could you provide an example of the shape of theresultthat comes from the API? For example, that could be a typo that's supposed to sayresult.user? It's impossible to say without seeing an example of what JSON comes back from/api/v1/auth/login.