Why the function is invoked for every input in React component? - javascript

I try to learn react component rendering but the problem is that I have a login page with 2 input field and 1 button as:
function LoginPage() {
const [username, changeUsername] = useState('');
const [password, changePassword] = useState('');
const loginRequest = async (username, password) => {
let response = await service.loginRequest(username, password);
console.log(response);
}
return (
<Card hoverable className='transaction-button-card'>
<h1>Enter username and password</h1>
<input type="text"
placeholder="Username"
onChange={e => changeUsername(e.target.value)}
value={username}></input>
<input type="text"
placeholder="Password"
onChange={e => changePassword(e.target.value)}
value={password}></input>
<Button onClick={loginRequest(username, password)}
className='withdraw-deposit-button'>Login/Deposit</Button>
</Card>
);
}
export default LoginPage;
When the page is rendered the function loginRequest(username, password) automatically triggered once and for every input characters to input fields are also triggering the same function and sending request for each input char. How can I solve this problem? (I don't want to send request automatically when the page is opened and send request with only with button). I would appreciate if you define the problem.

`
function LoginPage() {
const [username, changeUsername] = useState('');
const [password, changePassword] = useState('');
const loginRequest = async (username, password) => {
let response = await service.loginRequest(username, password);
console.log(response);
}
return (
<Card hoverable className='transaction-button-card'>
<h1>Enter username and password</h1>
<input type="text"
placeholder="Username"
onChange={e => changeUsername(e.target.value)}
value={username}></input>
<input type="text"
placeholder="Password"
onChange={e => changePassword(e.target.value)}
value={password}></input>
<Button onClick={() => loginRequest(username, password)}
className='withdraw-deposit-button'>Login/Deposit</Button>
</Card>
);
}
export default LoginPage;
`

Related

Objects are not valid as a React child (found: object with keys {})

I am having trouble on posting the error from data after submit incorrect mail and password. With debugger i'm seeing error text, but the page has error: Objects are not valid as a React child (found: object with keys {}). If you meant to render a collection of children, use an array instead.
import { signInWithEmailAndPassword } from 'firebase/auth';
import React, {useState} from 'react';
import auth from '../../Firebase/firebase';
const SignIn = (errorCode) => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [errorText, setErrorText] = useState(false);
const signIn = (e) => {
e.preventDefault();
signInWithEmailAndPassword(auth, email, password)
.then((userCredential) => {
console.log(userCredential);
})
.catch((error) => {
let errorCode = error.code;
let errorMessage = error.message;
debugger;
console.log(errorCode)
return (
setErrorText(true))
})
}
return (
<div>
<form onSubmit={signIn}>
<h1>Hey, Log In</h1>
<input type='email' placeholder='enter email' value={email} onChange={(e) => setEmail(e.target.value)}></input>
<input type='password' placeholder='enter pass' value={password} onChange={(e) => setPassword(e.target.value)}></input>
{ errorText ? <div>{errorCode}</div> : null
}
<button type='submit'>Push to login</button>
</form>
</div>
)
}
export default SignIn
I expected to image errorCode at the page signIn. Please, help me.
Hey you can declare the error code in global scope using useState like below and can follow below thread for looking into this kind of errors https://stackabuse.com/bytes/fix-objects-are-not-valid-as-a-react-child-error-in-react/
import React, { useState } from "react";
const SignIn = () => {
const [errorCode, setErrorCode] = useState("");
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [errorText, setErrorText] = useState(false);
const signIn = (e) => {
e.preventDefault();
setErrorCode('400')
console.log(errorCode);
setErrorText(true);
};
return (
<div>
<form onSubmit={signIn}>
<h1>Hey, Log In</h1>
<input
placeholder="enter email"
value={email}
onChange={(e) => setEmail(e.target.value)}
></input>
<input
type="password"
placeholder="enter pass"
value={password}
onChange={(e) => setPassword(e.target.value)}
></input>
{errorText ? <div>Error code {errorCode}</div> : null}
<button type="submit">Push to login</button>
</form>
</div>
);
};
export default SignIn;

TypeError: a.preventDefault is not a function

I'm trying to register auth with firebase using the name, email and password, but when I tried to register with that info then give me an error, like this:
TypeError: a.preventDefault is not a function
11 | const dispatch = useDispatch();
12 |
13 | const loginToDo = (a) => {
> 14 | a.preventDefault();
| ^ 15 | };
16 |
17 | const register = () => {
I'm sure my firebase connect is ok, because before I have save post data from this project,
so, I have tried code like this way:
import React, { useState } from "react";
import { auth } from "./firebase";
import "./Login.css";
import { useDispatch } from "react-redux";
const Login = () => {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [name, setName] = useState("");
const [profile, setProfile] = useState("");
const dispatch = useDispatch();
const loginToDo = (a) => {
a.preventDefault();
};
const register = () => {
if (!name) {
return alert("Please enter a name");
}
auth
.createUserWithEmailAndPassword(email, password)
.then((userAuth) => {
userAuth.user
.updateProfile({
displayName: name,
photoURL: profile,
})
.then(() => {
dispatch(
loginToDo({
email: userAuth.user.mail,
uid: userAuth.user.uid,
displayName: name,
photoURL: profile,
})
);
});
})
.catch((error) => alert(error));
};
return (
<div className="login">
<h2>
Please signUp or <br /> Login your account
</h2>
<form>
<input
value={name}
onChange={(e) => setName(e.target.value)}
type="text"
placeholder="Full name"
/>
<input
value={profile}
onChange={(e) => setProfile(e.target.value)}
type="text"
placeholder="Profile pic URL (optional)"
/>
<input
value={email}
onChange={(e) => setEmail(e.target.value)}
type="text"
placeholder="Email"
/>
<input
value={password}
onChange={(e) => setPassword(e.target.value)}
type="password"
placeholder="Password"
/>
<button type="submit" onClick={loginToDo}>
SignIn
</button>
</form>
<p style={{ marginTop: "10px" }}>
Not a member ?{" "}
<span className="login__register" onClick={register}>
Register Now
</span>
</p>
</div>
);
};
export default Login;
Any suggestion please!
A few things are somehow confusing in your code:
After Login:
<button type="submit" onClick={loginToDo}>
SignIn
</button>
function loginToDo will be called:
const loginToDo = (a) => {
a.preventDefault();
};
the page won't refresh and that's it. you haven't defined anything to happen after that.
In Signup
you call register function, inside, it dispatches this action:
dispatch(
loginToDo({
email: userAuth.user.mail,
uid: userAuth.user.uid,
displayName: name,
photoURL: profile,
})
loginToDo, as you defined just prevents page from refresh, it has nothing to do with your dispatch and actions. (also this is where the error comes from)
dispatch takes an object as argument, which usually has two properties: type and payload.
const action={
type:"registerUser" // the type depends on how you designed your reducer.
payload:userData // email, name, ...
}
dispatch(action)
sometimes people define actionCreators, that has the type itself, and only takes the payload:
const registerActionCreator=(payload)=>({type:"registerUser",payload:payload})
so alternatively you can use:
dispatch(registerActionCreator(userData))

React submit form returns event.preventDefault is not a function

I'm having a problem with a simple form registration submit. Here's the code:
import React from 'react';
import {register} from 'Util/api'
function Registration() {
const [email, setEmail] = React.useState("")
const [password, setPassword] = React.useState("")
const [passwordCheck, setPasswordCheck] = React.useState("")
const [error, setError] = React.useState("")
const register = event => {
event.stopPropagation()
event.preventDefault()
register(email, password, passwordCheck).then(res => {
console.log(res)
}).catch(error => {
console.log(error)
})
}
return (
<div>
<form onSubmit={register}>
<div>
<label>Email:
<input
type="text"
placeholder="Email"
value={email}
onChange={ev => setEmail(ev.target.value)}
/>
</label>
</div>
<div>
<label>Password:
<input
type="password"
placeholder="Password"
value={password}
onChange={ev => setPassword(ev.target.value)}
/>
</label>
</div>
<div>
<label>Repeat password:
<input
type="password"
placeholder="Repeat password"
value={passwordCheck}
onChange={ev => setPasswordCheck(ev.target.value)}
/>
</label>
</div>
<button type="submit" value="Submit">Register</button>
{error && (
<div>{error}</div>
)}
</form>
</div>
);
}
export default Registration
When I click the button "register" the console returns the error:
Registration.js:12 Uncaught TypeError: event.stopPropagation is not a function
Same thing happen with event.preventDefault if I delete that line. It looks very similar to the example in the doc here...
What's wrong with my code?
You have a name collision - there are 2 identifiers named register:
import {register} from 'Util/api'
and
const register = event => {
event.stopPropagation()
event.preventDefault()
register(email, password, passwordCheck).then(res => {
In the second code, you want to refer to the imported function, not the handler, but since the handler is lexically closer, register refers to the handler there - it calls itself recursively, with a first parameter of email, which is not actually an event, so stopPropagation and preventDefault can't be called on it.
Use a different name:
const handleSubmit = event => {
event.stopPropagation()
event.preventDefault()
register(email, password, passwordCheck).then(res => {
console.log(res)
}).catch(error => {
console.log(error)
})
}
<form onSubmit={handleSubmit}>
You have two register. Please change
const register = event =>
to
const submitHandler = event =>
and
<form onSubmit={register}>
to
<form onSubmit={submitHandler}>

React is calling function unexpectedly

Here is my Login component:
const Login = () => {
const [user, setUser] = useState("");
const [pass, setPass] = useState("");
return (
<div>
<p>Login</p>
<input
type="text"
onChange={(e) => {
setUser(e.target.value);
}}
/>
<input
type="password"
onChange={(e) => {
setPass(e.target.value);
}}
/>
<button onClick={submit(user, pass)}>
Submit
</button>
</div>
);
};
It renders on my webpage, but it calls the submit() function whenever I input to these two: text and password. Looking at my code, I've only set the onClick to call the submit function.
Is there something wrong with my code?
EDIT: Removed classNames for easier viewing
You are calling the submit function on every render. onClick takes a function, but you are directly calling a function.
<button onClick={submit(user, pass)}>
Submit
</button>
will be replaced by
<button onClick={()=>submit(user, pass)}>
Submit
</button>
try :
const Login = () => {
const [user, setUser] = useState("");
const [pass, setPass] = useState("");
const onSubmit = () => {
submit(user,pass)
}
return (
<div>
<p>Login</p>
<input
type="text"
onChange={(e) => {
setUser(e.target.value);
}}
/>
<input
type="password"
onChange={(e) => {
setPass(e.target.value);
}}
/>
<button onClick={onSubmit}>
Submit
</button>
</div>
);
};

React Axios Input Undefined

I must post {input} data to http://localhost:4000/prediction with Axios. But {input} turns undefined.
I am using const instead of class Main extends component. onChange, it sets form data.
const Main = ({ value, suggestions, auth: { user } }) => {
const [formData, setFormData] = useState("");
const [messages, setMessages] = useState([]);
const { input } = formData;
const onChange = e => setFormData(e.target.value);
const onSubmit = event => {
event.preventDefault();
setMessages(prevMsgs => [...prevMsgs, formData]);
console.log({ input });
Axios post.
axios
.post(
`http://localhost:4000/prediction`,
{ input },
{ crossdomain: true }
)
.then(res => {
console.log(res.data);
//setMessages(prevMsgs => [...prevMsgs, formData]);
})
.catch(error => {
console.log(error.message);
});
};
Return (form) with onSubmit, onChange.
return (
<div className="true">
<br />
<form noValidate onSubmit={e => onSubmit(e)}>
<div className="input-group mb-3">
<input
name="input"
type="text"
className="form-control"
placeholder="Type text"
onChange={e => onChange(e)}
/>
)}
<div className="input-group-append">
<button className="btn btn-outline-secondary">Send</button>
</div>
</div>
</form>
</div>
);
};
As I have mentioned in the comment section formData is a string as I see which does not have a property called input what you try to destructure and that's why it is undefined always.
If you really need that format for axios then you can try change the structure of formData with useState as the following first:
const [formData, setFormData] = useState({input: null});
Then maybe you can try updating as:
const onChange = e => setFormData({input: e.target.value});
I hope that helps!

Categories