I added two handlers to my code. First, mail is entered and handleStart is started, then the user name and password are obtained from the user, and then when the button is pressed, handleFinish is activated and information assignments are made. setEmail state works but password and name states do not
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [name, setName] = useState("");
const history = useHistory();
const url = "http://localhost:3002/register";
const emailRef = useRef();
const passwordRef = useRef();
const usernameRef = useRef();
const handleStart = () => {
setEmail(emailRef.current.value);
}
const handleFinish = async (e) => {
e.preventDefault();
console.log("ref data", passwordRef.current.value,usernameRef.current.value)
//it works and shows values
setPassword(passwordRef.current.value);
setName(usernameRef.current.value);
console.log("state data", email, password, name)
//status values are empty except for email
try {
await axios.post(url, { email, name, password });
history.push("/");
} catch (err) { }
}
and my return (HTML) codes:
{!email ? (
<div className="input">
<input type="email" placeholder="email address" ref={emailRef} />
<button className="registerButton" onClick={handleStart}>
Get Started
</button>
</div>
) : (
<form className="input">
<input type="username" placeholder="username" ref={usernameRef} />
<input type="password" placeholder="password" ref={passwordRef} />
<button className="registerButton" onClick={handleFinish}>
Start
</button>
</form>
)}
CodePudding user response:
It's better to use useState
to store and get values and control element rather then using ref
.
Here is the code using state, that may help you:
const App = () => {
const history = useHistory();
const url = "http://localhost:3002/register";
const [step, setStep] = useState(0)
const [email, setEmail] = useState("")
const [password, setPassword] = useState("")
const [username, setUsername] = useState("")
const handleStart = () => {
setStep(1)
}
const handleFinish = async (e) => {
e.preventDefault();
console.log("data: ", email, password, username)
try {
await axios.post(url, { email, name, password });
history.push("/");
} catch (err) { }
}
return (
step === 0 ? (
<div className="input">
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="email address"
/>
<button className="registerButton" onClick={handleStart}>
Get Started
</button>
</div>
) : (
<form className="input">
<input
type="username"
placeholder="username"
value={username}
onChange={(e) => setUsername(e.target.value)}
/>
<input
type="password"
placeholder="password"
value={password}
onChange={() => setPassword(e.target.value)}
/>
<button className="registerButton" onClick={handleFinish}>
Start
</button>
</form>
)
)
}
CodePudding user response:
This is very well known problem, explained thousands time here,
that state changes are internally asynchronous means we wont get updated state on next line immediately, it takes time to complete execution of setPassword
and setName
, so next line after set state, console.log would be old values
console.log(passwordRef.current.value)
console.log(usernameRef.current.value)
this must have values, and logged on console but not password
and name
this below behavior is correct, known and no issues here,
console.log("state data", email, password, name)
//status values are empty except for email
better would be, this below hack works always for me,
await axios.post(url, { email, usernameRef.current.value, passwordRef.current.value });
CodePudding user response:
If you wish to do some activity based on value change for email, password, name using useEffect could be a better option. You can call API or perform any activity as an effect of those values change. Please find following code -
useEffect(() => {
await axios.post(url, { email, name, password });
history.push("/");
return () => {
// handle cancelling or other clean up
}
}, [email, password, name]);