import { useState, useNavigate } from "react";
function Register() {
const [formData, setFormData] = useState();
const [errors, setErrors] = useState([]);
async function handleSubmit(e) {
e.preventDefault();
let res = await fetch("http://localhost:5000/api/register", {
method: "POST",
body: new URLSearchParams(new FormData(e.target)),
});
res = await res.json();
if (res === true) return useNavigate("/posts");
setErrors(res.errors);
setFormData(res.formData);
}
return (
<main>
<h1>Register</h1>
<form onSubmit={(e) => handleSubmit(e)}>
<div>
<label>
Username:{" "}
<input
type="text"
name="username"
required
minLength={3}
defaultValue={formData && formData.username}
/>
</label>
</div>
<div>
<label>
Email:{" "}
<input
type="email"
name="email"
required
defaultValue={formData && formData.email}
/>
</label>
</div>
<div>
<label>
Password: <input type="password" name="password" required minLength={8} />
</label>
</div>
<br />
<button>Register</button>
</form>
{errors.length > 0 && (
<>
<h3>Errors</h3>
<ul>
{errors.map((error) => (
<li key={crypto.randomUUID()}>{error.msg}</li>
))}
</ul>
</>
)}
</main>
);
}
export default Register;
#How do I redirect with React? (useNavigate isn't working)
8 messages · Page 1 of 1 (latest)
router.post(
"/register",
body("username")
.escape()
.trim()
.isLength({ min: 3 })
.withMessage("Username must be at least 3 characters")
.isAlphanumeric()
.withMessage("Username can only have letters or numbers"),
body("email").escape().trim(),
body("password")
.escape()
.trim()
.isLength({ min: 8 })
.withMessage("Password must be at least 8 characters"),
(req, res) => {
bcrypt.hash(req.body.password, 10, async (err, hashedPassword) => {
const newUser = new User({
username: req.body.username,
email: req.body.email,
password: hashedPassword,
});
const errors = validationResult(req);
if (errors.isEmpty()) {
await newUser.save();
res.json(true);
} else {
res.json({
errors: errors.array(),
formData: newUser,
});
}
});
}
);```
If the backend returns true (meaning the register account worked) I want to redirect to /posts.
useNavigate isn't working because it's not in a React component, but when I put it in a React component it still says it can't be called conditionally. How do I fix this? Is there an easier way to do what I want?
that's not how useNavigate is used. check the docs
Oh... I realised I was importing it from react and not react-router-dom. Now it works, thank you
Is there a better way to redirect them other than returning true if the register was successful?
Has nothing to do with importing it from the wrong place. You were not using it properly at all…
import { useState } from "react";
import { useNavigate } from "react-router-dom";
function Register() {
const [formData, setFormData] = useState();
const [errors, setErrors] = useState([]);
const navigate = useNavigate();
async function handleSubmit(e) {
e.preventDefault();
console.log(1);
let res = await fetch("http://localhost:5000/api/register", {
method: "POST",
body: new URLSearchParams(new FormData(e.target)),
});
console.log(2);
res = await res.json();
console.log(3);
if (res === true) {
console.log("Redirecting");
return navigate("/posts");
}
console.log(4);
setErrors(res.errors);
setFormData(res.formData);
console.log(5);
}
return (
<main>
<h1>Register</h1>
<form onSubmit={(e) => handleSubmit(e)}>
<div>
<label>
Username:{" "}
<input
type="text"
name="username"
required
minLength={3}
defaultValue={formData && formData.username}
/>
</label>
</div>
<div>
<label>
Email:{" "}
<input
type="email"
name="email"
required
defaultValue={formData && formData.email}
/>
</label>
</div>
<div>
<label>
Password: <input type="password" name="password" required minLength={8} />
</label>
</div>
<br />
<button>Register</button>
</form>
{errors.length > 0 && (
<>
<h3>Errors</h3>
<ul>
{errors.map((error) => (
<li key={crypto.randomUUID()}>{error.msg}</li>
))}
</ul>
</>
)}
</main>
);
}
export default Register;
I added const navigate = useNavigate(); at the top as well, am I using it correctly now?
Yes