I am trying to use a common form component for the Register and Login section, I am using Tabs (register and login). when I store data "name" in the register state and then switch the tab to login and then come back then the registered state variable is wiped clean.
Should I just write 2 different forms or is there a better way to write it?
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { useState } from "react";
const RegisterAndLoginForm = ({name}) => {
const [registerForm, setRegisterForm] = useState({name:""});
const [loginForm, setLoginForm] = useState({});
const handleRegisterInput = (e) =>{
setRegisterForm({...registerForm, [e.target.name]: e.target.value});
}
console.log("reg->",registerForm);
const handleLoginInput = (e) =>{
setLoginForm({...loginForm, [e.target.name]: e.target.value})
}
const handleSubmit = (e) =>{
e.preventDefault();
}
const clearForm = () =>{
}
const convertToBase64 = (e) => {
const file = e.target.files[0];
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
setRegisterForm({ ...registerForm, avatar: reader.result });
};
};
return (
<main className="bg-transparent_bg w-full flex flex-col items-center box-border rounded-md">
<form
className="w-full text-center space-y-3 p-2 box-border"
onSubmit={handleSubmit}
>
<h3 className="font-extrabold text-foreground text-xl bg-slate-500 py-2 rounded-md tracking-widest">
{name}
</h3>
{name === "Register" && (<label htmlFor="name">Name :</label>)}
{name === "Register" && (<input
id="name"
className="input"
type="text"
placeholder="name"
name="name"
value={registerForm?.name}
onChange={(e)=>handleRegisterInput(e)}
/>)}
<label htmlFor="username">Username: </label>
<input
id="username"
className="input"
type="text"
placeholder="username"
name="username"
// value={postData.title}
onChange={name === "Register" ? handleRegisterInput : handleLoginInput}
/>
{name === "Register" && (<label htmlFor="email">Email: </label>)}
{name === "Register" && (<input
id="email"
className="input"
type="text"
placeholder="username"
name="username"
// value={registerForm?.title}
onChange={handleRegisterInput}
/>)}
<label htmlFor="password">Password: </label>
<input
id="password"
className="input"
type="password"
placeholder="password"
name="password"
// value={postData.title}
onChange={name === "Register" ? handleRegisterInput : handleLoginInput}
/>
{name === "Register" && (<label htmlFor="confirmPassword">Confirm password: </label>)}
{name === "Register" && (<input
id="confirmPassword"
className="input"
type="password"
placeholder="confirm assword"
name="confirmPassword"
// value={postData.title}
onChange={handleRegisterInput}
/>)}
{name === "Register" && (<div className="w-full bg-slate-500 text-foreground py-2 px-1 rounded-md overflow-hidden">
<input
className="text-[12px] font-medium cursor-pointer"
type="file"
onChange={convertToBase64}
/>
</div>)}
<div className="flex justify-center gap-5 py-1 box-border">
<button
type="submit"
className="bg-blue-400 w-24 px-3 py-2 rounded-md hover:bg-blue-500 active:bg-blue-600 text-white tracking-widest"
>
{name}
</button>
<button
onClick={clearForm}
type="button"
className="bg-red-500 w-24 px-3 py-2 rounded-md hover:bg-red-600 active:bg-red-700 text-white tracking-widest"
>
Clear
</button>
</div>
</form>
</main>
);
};
const LoginAndRegister = () => {
return (
<div className="grid m-auto grid-cols-2">
<div>
<Tabs defaultValue="register" className="w-[500px] p-1">
<TabsList className="w-full">
<TabsTrigger value="register" className="w-[50%]">
Register
</TabsTrigger>
<TabsTrigger value="login" className="w-[50%]">
Login
</TabsTrigger>
</TabsList>
<TabsContent value="register" className="border rounded-md">
<RegisterAndLoginForm name={"Register"} />
</TabsContent>
<TabsContent value="login" className="border rounded-md">
<RegisterAndLoginForm name={"Login"} />
</TabsContent>
</Tabs>
</div>
<div>memories logo</div>
</div>
);
};
export default LoginAndRegister;
You can try using the context API so that you can refer to, for example, the register form data.
/* ... */
import { createContext, useState, useContext } from "react";
const RegisterFormContext = createContext(null);
const RegisterAndLoginForm = ({name, setRegisterForm}) => {
const registerForm = useContext(RegisterFormContext);
/* ... */
};
const LoginAndRegister = () => {
const [registerForm, setRegisterForm] = useState({name: ""});
return (
<RegisterFormContext.Provider value={registerForm}>
<div className="grid m-auto grid-cols-2">
/* ... */
</div>
</RegisterFormContext.Provider>
);
};
export default LoginAndRegister;
As you can see, you'd need to pass the parent's setRegisterForm
callback to the RegisterAndLoginForm
component.
As you've commented, contexts aren't necessary for this. They are more often used where a value stack is really necessary.