What I'm trying to achieve is that I want a user to be able to submit a registration only when they follow the correct guidelines, such as having a minimum of 8 characters, etc. I have a button set up with a Link router:
//CSS
import "./Register.css"
//LOCAL LIBRARIES
import { VoidFunc, ChangeEventHandlerType,
FormEventHandlerType } from "./index"
import useSubmit from "../../Hooks/Register/useSubmit";
//EXTERNAL LIBRARIES
import { Link } from "react-router-dom";
const Register = () => {
{...}
//Manage Admin
const [username, password, confirmPassword, handleChange,
handleSubmit, placeholder, error, registerUser] = useSubmit()
return (
<div className="div-register">
{...}
<form className="form-register"
onSubmit={handleSubmit as FormEventHandlerType}>
{...}
<Link className="link-register" to={registerUser as string}>
<button className="btn-submit-register">Submit</button>
</Link>
{...}
</form>
</div>
);
};
export default Register;
My attempt was to use a useState hook to manage the url destination of the component so that when the input fields are not filled in properly, the Links "to" property is set to "/register" (keeping the user on the same page they are already on), and when they are, it is set to "/admin" which is the main logged in destination.
I have another .tsx file where I refactored a few elements into one arrow function. The bits I cut out just had conditions like "If the user didnt fill out a field, add an error text to the placeholder for that input field":
//LOCAL
import RegisterUser from "../../Components/Register/RegisterUser";
//EXTERNAL
import { useState } from "react";
import {iState, StateType,
ChangeEventType, FormEventType} from
"../../Pages/Register/index"
const useSubmit = () =>{
//Number Check
let hasNumber = /\d/;
//Error
const [error, setError] = useState<string>("")
//Is Password valid
const [registerUser, setRegisterUser] = useState<string>("/register")
//Placeholder
const [placeholder, setPlaceholder] = useState<string>("")
//Manage Admin
const [state, setState] = useState<StateType>(iState)
const {username, password, confirmPassword} = state
const handleChange = (event: ChangeEventType) => {
//unfinished code
event.preventDefault()
const {name, value} = event.target
setState({...state, [name]: value})
console.log(state)
}
const handleSubmit = (event: FormEventType) => {
event.preventDefault()
{...FAILURE CONDITIONS}
//SUCCESS BLOCK
else {
setPlaceholder("")
setError("")
setRegisterUser("/admin")
}
}
return [username, password,
confirmPassword, handleChange, handleSubmit, placeholder,
error, registerUser]
}
export default useSubmit;
Any help is appreciated!
It seems you are really just wanting to navigate to "/admin"
from the submit handler. For this you should use an imperative navigation instead of the Link
. (1) the Link
's click handler won't wait for the form
element's onSubmit
handler to complete, and (2) it certainly can't wait for the registerUser
state to update.
Use the useHistory
hook to access the history
object if you are using react-router-dom@5
or the useNavigate
hook to access the navigate
function if you are using react-router-dom@6
.
useSubmit
Import and use either useHistory
or useNavigate
hooks, depending on installed version, and invoke in the submit handler on the success logic branch. Remove the registerUser
state. Return an object instead of an array so destructuring assignment doesn't depend on array indices.
import { useHistory } from 'react-router-dom'; // RRDv5
import { useNavigate } from 'react-router-dom'; // RRDv6
const useSubmit = () => {
const history = useHistory(); // RRDv5
const navigate = useNavigate(); // RRDv6
// Number Check
let hasNumber = /\d/;
// Error
const [error, setError] = useState<string>("");
// Placeholder
const [placeholder, setPlaceholder] = useState<string>("");
// Manage Admin
const [state, setState] = useState<StateType>(iState);
const {username, password, confirmPassword} = state;
const handleChange = (event: ChangeEventType) => {
// unfinished code
event.preventDefault()
const { name, value } = event.target;
setState(state => ({
...state,
[name]: value
}));
}
const handleSubmit = (event: FormEventType) => {
event.preventDefault()
{...FAILURE CONDITIONS}
// SUCCESS BLOCK
else {
history.replace("/admin"); // RRDv5
navigate("/admin", { replace: true }); // RRDv6
}
}
return {
username,
password,
confirmPassword,
handleChange,
handleSubmit,
placeholder,
error,
};
};
Register
Remove the Link
component wrapping the submit button, unnecessary. Use object destructuring assignment from the useSubmit
hook.
const Register = () => {
...
// Manage Admin
const {
username,
password,
confirmPassword,
handleChange,
handleSubmit,
placeholder,
error,
} = useSubmit();
return (
<div className="div-register">
...
<form
className="form-register"
onSubmit={handleSubmit as FormEventHandlerType}
>
...
<button className="btn-submit-register">Submit</button>
...
</form>
</div>
);
};