I am having an issue understanding why my react component is throwing an error with my form. If I hit enter it does not work as expected as in it does nothing. If I click it will work but it will spam error out until I refresh with this error:
Expected onClick
listener to be a function, instead got a value of string
type.
Now that being said here is my form and then entire file:
<div className="form-group">
<form onSubmit={()=>onSubmit()}>
<input type="submit" className="form-control" />
</form>
</div>
import React from "react";
import { FaSignInAlt } from "react-icons/fa";
import { ToastContainer } from "react-toastify";
import 'react-toastify/dist/ReactToastify.css';
import { useState, useEffect } from "react";
import { useNavigate } from "react-router-dom";
import { useSelector, useDispatch } from "react-redux";
import { toast } from "react-toastify";
import { login, reset } from "../features/authSlice";
import Spinner from "../Components/Spinner";
const Login = () => {
const [formData, setFormData] = useState({
alias: "",
password: "",
});
const { alias, password } = formData;
const navigate = useNavigate();
const dispatch = useDispatch();
const { user, isLoading, isError, isSuccess, message } = useSelector(
(state) => state.auth
);
useEffect(() => {
if (isError) {
toast.error(message)
}
if (isSuccess || user) {
navigate('/')
}
dispatch(reset())
}, [user, isError, isSuccess, message, navigate, dispatch])
const handleOnChange = (e) => {
setFormData((prevState) => ({
...prevState,
[e.target.name]: e.target.value,
}));
};
const onSubmit = (e) => {
const userData = {
alias,
password,
};
dispatch(login(userData));
};
if (isLoading) {
return <Spinner />
}
return (
<div>
<section className="heading">
<h1>
<FaSignInAlt /> Login
</h1>
<p>Please login</p>
</section>
<section>
<div className="form-group">
<form>
<input
type="text"
className="form-control"
id="alias"
name="alias"
value={alias}
placeholder="enter your alias"
onChange={handleOnChange}
/>
</form>
</div>
<div className="form-group">
<form>
<input
type="text"
className="form-control"
id="password"
name="password"
value={password}
placeholder="enter your password"
onChange={handleOnChange}
/>
</form>
</div>
<div className="form-group">
<form onSubmit={()=>onSubmit()}>
<input type="submit" className="form-control" />
</form>
</div>
</section>
</div>
);
};
export default Login;
I tried switching the onSubmit to onClick and removing the lambda function in the {} braces
3
Answers
There is no reason for you to have this error in the code you are showing, but your form is incorrect. You might need to remove the
form
tag around your inputs. Only one is necessary, wrapping your whole form.If it does not resolve your problem, please try to provide a repro on stackblitz or codesandbox so we can check it out.
You created multiple forms in your example and then submitted only the last one. (If you really wanted to do this, you would need to do some more programming.)
To resolve your issue, you need to fix two bugs:
e.preventDefault();
.Because the button has the type "submit", it calls automatically the form’s
onSubmit
function. You can read more about forms and submitting in the new react documentation.Why are all your form elements in different form tags? If it is for styling purposes, you can instead put them in
div
s and then style them using classes, but if you want to handle the submit of the form with the elements in them, then you can do something like thisAlso, you recieved the event
e
in your function but you didn’t pass it in your callback function.You can instead just pass the function without calling it and the event will be passed automatically:
Note: You can also use
onClick
but instead of having the<input type="submit" className="form-control" />
, you can rather have a<button class="form-control" onClick={onSubmit}></button>
and hence, the onSubmit attribute can be removed from the<form>
‘s opening tagBy the way, you can try naming your submit function something like
handleSubmit
instead ofonSubmit
to avoid confusion 🙂