#How do I redirect with React? (useNavigate isn't working)

8 messages · Page 1 of 1 (latest)

old cape
#
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;
#
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?

fathom prawn
#

that's not how useNavigate is used. check the docs

old cape
fathom prawn
#

Has nothing to do with importing it from the wrong place. You were not using it properly at all…

old cape
#
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?

fathom prawn
#

Yes