I am new to Next.js so I am looking for solution for my problem and advice in the same time.
Problem:
-On the empty URL (just localhost:8081) I have a login form, with the option to switch to the Register component without refreshing or changing the URL. If I successfully register the text pops up with the message "Successful register" and it disappears after 2.5 seconds and then renders the Login Component for a user to log in.
At the login component if the user inputs the wrong username/password, the text "Wrong username/password" will appear.
The problem is that there are 2 separate CSS files for the Register and Login components, the text for the Register component is blue, and for Login is red, but when I input the wrong username/password on the Login Component the text is blue. When I inspect the code the color: red; CSS par is crossed, so I guess there is a CSS conflict there.
I import CSS files for both Components in the Components files.
Page.js file:
"use client"
import React, { useState } from 'react';
import LoginForma from "./components/LoginForma/LoginForma";
import Register from './components/Register/Register';
const Login = () => {
const [showRegistration, setShowRegistration] = useState(false);
const [showLogin, setShowLogin] = useState(false);
const handleRegisterClick = () => {
setShowRegistration(true);
setShowLogin(false);
};
const handleLoginClick = () => {
setShowLogin(true);
setShowRegistration(false);
};
return (
<div>
{!showRegistration && !showLogin && <LoginForma onRegisterClick={handleRegisterClick} />}
{showRegistration && <Register onLoginClick={handleLoginClick} />}
{showLogin && <LoginForma onRegisterClick={handleRegisterClick} />}
</div>
)
}
export default Login;
Login component file:
"use client"
import React from "react";
import "./LoginForma.css";
import axios from 'axios';
import { useRouter } from "next/navigation";
import { useForm } from "react-hook-form";
const LoginForma = ({ onRegisterClick }) => {
const router = useRouter();
const {
register,
handleSubmit,
formState: { errors }
} = useForm();
const onSubmit = async (data) => {
const formData = new FormData();
formData.append('username', data.username);
formData.append('password', data.password);
axios.post('http://localhost:8000/token', formData)
.then(async (response) => {
const uloga = await axios.get(`http://localhost:8000/get-data/${data.username}`);
localStorage.setItem('token', response.data.access_token);
router.push(`http://localhost:8081/home-${uloga.data}`)
})
.catch((error) => {
if (error.response && error.response.status === 401) {
const h2Elemenet = document.getElementsByTagName("h2")[0];
h2Elemenet.classList.toggle("hidden");
} else {
setLoginError("Došlo je do greške prilikom prijave. Molimo, pokušajte ponovo.");
}
});
};
return (
<div className="wrapper">
<form onSubmit={handleSubmit(onSubmit)}>
<h1>Login</h1>
<h2 className="hidden">Pogresan username/password!</h2>
<div className="input-box">
<input type="text" placeholder="Username" name="username" {...register('username', { required: true })} />
</div>
<div className="input-box">
<input type="password" placeholder="Password" name="password" {...register('password', { required: true })} />
</div>
<div className="input-box">
<button type="submit">Login</button>
</div>
<div className="register-link">
<p>Nemate nalog? <a onClick={onRegisterClick}>Registrujte se</a> </p>
</div>
</form>
</div>
)
}
export default LoginForma
Register Component main file:
"use client"
import React, { useState } from "react";
import RegisterVlasnik from "../RegisterVlasnik/RegisterVlasnik";
import RegisterSportista from "../RegisterSportista/RegisterSportista";
const Register = ({ onLoginClick }) => {
const [showRegisterSportista, setShowRegisterSportista] = useState(true);
const [showRegisterVlasnik, setShowRegisterVlasnik] = useState(false);
const iconClick = () => {
setShowRegisterSportista(!showRegisterSportista);
setShowRegisterVlasnik(!showRegisterVlasnik);
};
return (
<div>
{showRegisterSportista && (
<RegisterSportista
onLoginClick={onLoginClick}
iconClick={iconClick}
/>
)}
{showRegisterVlasnik && (
<RegisterVlasnik
onLoginClick={onLoginClick}
iconClick={iconClick}
/>
)}
</div>
);
}
export default Register;
Register component for one type of users:
"use client"
import "../RegisterSportista/RegisterSportista.css";
import axios from 'axios';
import { useForm } from "react-hook-form";
import { MdOutlineChangeCircle } from "react-icons/md";
const RegisterVlasnik = ({ onLoginClick, iconClick }) => {
const {
register,
handleSubmit,
formState: { errors }
} = useForm();
const onSubmit = async (data) => {
axios.post('http://localhost:8000/register/vlasnik', {
username: data.username,
sifra: data.password,
mail: data.email,
kontakt: data.kontakt,
ime: data.ime,
prezime: data.prezime,
spol: data.spol,
racun: data.racun
}).then((response) => {
const h2Elemenet = document.getElementsByTagName("h2")[0];
h2Elemenet.classList.toggle("hidden");
setTimeout(()=>onLoginClick(),2500);
}, (error) => {
console.log("Error: ", error)
});
};
return (
<div className="wrapper">
<form onSubmit={handleSubmit(onSubmit)}>
<h1>Register Vlasnik <span onClick={iconClick}><MdOutlineChangeCircle /></span></h1>
<h2 className="hidden">Uspesna registracija, ulogujte se!</h2>
<div className="input-box">
<input type="text" placeholder="Ime" name="ime" {...register('ime', { required: true })} />
</div>
<div className="input-box">
<input type="text" placeholder="Prezime" name="prezime" {...register('prezime', { required: true })} />
</div>
<div className="input-box">
<input type="text" placeholder="E-mail" name="email" {...register('email', { required: true })} />
</div>
<div className="input-box">
<input type="text" placeholder="Username" name="username" {...register('username', { required: true })} />
</div>
<div className="input-box">
<input type="password" placeholder="Password" name="password" {...register('password', { required: true })} />
</div>
<div className="input-box">
<input type="text" placeholder="Kontakt" name="kontakt" {...register('kontakt', { required: true })} />
</div>
<div className="input-box">
<input type="text" placeholder="Racun" name="racun" {...register('racun', { required: true })} />
</div>
<div className="input-box">
<select name="spol" {...register('spol', { required: true })}>
<option value="">Izaberite pol</option>
<option value="musko">Musko</option>
<option value="zensko">Zensko</option>
</select>
</div>
<div className="input-box">
<button type="submit">Registruj se</button>
</div>
<div className="register-link">
<p>Imate nalog? <a onClick={onLoginClick}>Ulogujte se</a></p>
</div>
</form>
</div>
)
}
export default RegisterVlasnik;
Register component for the other type of user:
"use client"
import "./RegisterSportista.css";
import axios from 'axios';
import { useForm } from "react-hook-form";
import { MdOutlineChangeCircle } from "react-icons/md";
const RegisterSportista = ({ onLoginClick, iconClick }) => {
const {
register,
handleSubmit,
formState: { errors }
} = useForm();
const onSubmit = async (data) => {
axios.post('http://localhost:8000/register/sportista', {
username: data.username,
sifra: data.password,
mail: data.email,
ime: data.ime,
prezime: data.prezime,
spol: data.spol,
referal: data.referalCode ? data.referalCode : null,
racun: data.racun
})
.then((response) => {
const h2Elemenet = document.getElementsByTagName("h2")[0];
h2Elemenet.classList.toggle("hidden");
setTimeout(()=>onLoginClick(),2500);
}, (error) => {
console.log("Greska: ", error)
});
};
return (
<div className="wrapper">
<form onSubmit={handleSubmit(onSubmit)}>
<h1>Register Sportista <span onClick={iconClick}><MdOutlineChangeCircle /></span></h1>
<h2 className="hidden">Uspesna registracija, ulogujte se!</h2>
<div className="input-box">
<input type="text" placeholder="Ime" name="ime" {...register('ime', { required: true })} />
</div>
<div className="input-box">
<input type="text" placeholder="Prezime" name="prezime" {...register('prezime', { required: true })} />
</div>
<div className="input-box">
<input type="text" placeholder="E-mail" name="email" {...register('email', { required: true })} />
</div>
<div className="input-box">
<input type="text" placeholder="Username" name="username" {...register('username', { required: true })} />
</div>
<div className="input-box">
<input type="password" placeholder="Password" name="password" {...register('password', { required: true })} />
</div>
<div className="input-box">
<input type="text" placeholder="Referal Code" name="referalCode" {...register('referalCode')} />
</div>
<div className="input-box">
<input type="text" placeholder="Racun" name="racun" {...register('racun', { required: true })} />
</div>
<div className="input-box">
<select name="spol" {...register('spol', { required: true })}>
<option value="">Izaberite pol</option>
<option value="musko">Musko</option>
<option value="zensko">Zensko</option>
</select>
</div>
<div className="input-box">
<button type="submit">Registruj se</button>
</div>
<div className="register-link">
<p>Imate nalog? <a onClick={onLoginClick}>Ulogujte se</a></p>
</div>
</form>
</div>
)
}
export default RegisterSportista;
The first and second type of users use the same CSS file and that is okay, but the Login and main Register components use separate CSS files but they somehow mix up.
I tried adding !important after color: red and it works but that is not much of a solution.
Folder structure:
-Register.jsx connects RegisterSportista.jsx and RegisterVlasnik.jsx. Both Register.jsx and LoginForma.jsx are called in Page.js file.
2
Answers
you use css for components in wrong way. read about CSS modules.
https://nextjs.org/docs/app/building-your-application/styling/css-modules
in this way styles will be encapsulated for components and will not affect on different one
in your case you sould store
LoginForma.css";
on the same level as your LoginForma component and rename it likeLoginForma.module.css
and import it likeimport styles from "./LoginForma.module.css";
After that in component when you need use class from styles it should looks like this
<div className={styles['class-name-from-file']}></div>
In the next js, you should use CSS module styling or use an external library such as tailwind or bootstrap. I prefer tailwind