I'm new to React and have been trying to make a registration form, but I couldn't find a way to get data from my input when a button is clicked (onClick)
function App() {
const userData = []
function handleClick() {
//get input data here
}
return (
<div className="form-main">
<div className='em'>
<label className='label '> User e-mail </label>
<Input type="email" />
</div>
<div className='pw'>
<label className='label '> Password </label>
<Input type="password" />
</div>
<button type="submit" className="submit-btn" onClick={handleClick}>Signup</button>
</div>
);
}
I've shared my input component below in case that helps (I've shortened the code while posting)
function Input(props) {
return (
<input type={props.type} className="input"></input>
);
}
Your form inputs are uncontrolled - https://reactjs.org/docs/forms.html#controlled-components
Updates to the value of the input aren't being registered by React. A quick stripped down working version to give you an idea of how it works:
const Form = () => {
const [email, setEmail] = useState('');
const handleSubmit = (event) => {
event.preventDefault();
// ... do something with email
}
return (
<form onSubmit={handleSubmit}>
<input type='email' value={email} onChange={(e) => { setEmail(e.target.value) }} />
<button type='submit'>Submit</button>
</form>
);
}
In this way React is 'controlling' the input and you can do whatever you like with the email value in the handleSubmit() function.
You can make use of useRef here . Just call handleSubmit when submit button is clicked as shown below .
const Form = () => {
const emailRef = React.useRef(null);
const handleSubmit = (event) => {
event.preventDefault();
// ... make use of your email data entered inside input
console.log(emailRef.current.value) // consoles the email
}
return (
<form onSubmit={handleSubmit}>
<input type='email' ref={emailRef} />
<button type='submit' onClick={handleSubmit}>Submit</button>
</form>
);
}
You can get more clarity on useRef here official doc
Related
Why is my code not working? I'm creating a registration form and I'm wanting to add an error message if the passwords do not match. Why is it not letting me dynamically add para tag to my html? Adding some more text here as I'm getting a post is mostly code error......
import React from 'react'
import Navbar from './components/Navbar'
import { Link } from 'react-router-dom'
import './Register.css'
import { useState, useRef } from 'react'
import { createUserWithEmailAndPassword } from "firebase/auth";
import { auth } from './firebase'
function Register() {
const div = useRef(null);
const handleSubmit = event => {
if (password == confirmPassword) {
createUserWithEmailAndPassword(auth, registerEmail, confirmPassword)
.then((userCredential) => {
// Signed in
const user = userCredential.user;
// ...
})
.catch((error) => {
const errorCode = error.code;
const errorMessage = error.message;
// ..
});
}
else {
//problem
var passNotMatch = document.createElement('p');
passNotMatch.innerHTML = "Passwords do not match, please try again.";
div.appendChild(passNotMatch);
event.preventDefault();
}
}
return (
<>
<Navbar />
<div className='signup-div'>
<div useRef={div}>
<h2>Register</h2>
<form onSubmit={handleSubmit}>
<input className='input input_email' type="email" placeholder='Email Address' value={registerEmail} onChange={e => setRegisterEmail(e.target.value)} required /> <br />
<input className='input input_password' type="password" placeholder='Set password' value={password} onChange={e => setPassword(e.target.value)} required /> <br />
<input className='input input_password' type="password" placeholder='Confirm password' value={confirmPassword} onChange={e => setConfirmPassword(e.target.value)} required /> <br />
<button type='submit' className='register-button'>Register</button>
<Link to='/signin'>Already have an account? Sign In</Link>
</form>
</div>
</div>
</>
)
}
You're using React incorrectly. Directly interacting with the DOM is almost never the right approach in React. Instead, "dynamic" markup is conditionally included in the markup based on state values. For example, consider this markup structure:
return (
<>
<Navbar />
<div className='signup-div'>
<div>
<!-- the rest of your markup, then... -->
{showError ? <p>Passwords do not match, please try again.</p> : null}
</div>
</div>
</>
)
Note the conditional inclusion of the <p> element, based on the boolean value of showError. Which means showError is something you'd track in state:
function Register() {
const [showError, setShowError] = useState(false);
const handleSubmit = event => {
//...
}
//...
}
Its initial value is set to false, so the <p> won't be shown. Then you just update the state to true to show it:
else {
//problem
setShowError(true);
event.preventDefault();
}
You would also set it back to false wherever you want in your code. Perhaps at the beginning of the handleSubmit function for example.
Overall the concept is that you don't directly manipulate the DOM. Instead, you track the current "state" of things in state values. The rendering is based on the current state, and updates to the state trigger a re-render.
If I go to /products/ and add in the end anything, It will Search from all the products, but when I try to press the search button, it doesnt do anything, not even go to /products/.
I dont know if I should use Button instead of input, I'm following a tutorial and it works there
const Search = ({ history }) => {
const [keyword, setKeyword] = useState("");
const searchSubmitHandler = (e) => {
e.preventDefault();
if (keyword.trim()) {
history.push(`/products/${keyword}`);
} else{
history.push("/products");
}
};
return (
<Fragment>
<form className="searchBox" onSubmit={searchSubmitHandler}>
<input
type="text"
placeholder="Search a Product ..."
onChange={(e) => setKeyword(e.target.value)}
/>
<input type="submit" value="Search" />
</form>
</Fragment>
);
};
export default Search here
Try canceling
e.preventDefault ();
I want to send a form so I created a function for that. I have a submit form , and the button should not enable until all fields of the form are fully filled.
All validations are working but this is not a problem, I need it for an onclick event.
My code works but when I click the checkbox one time to make it true and click again to make it false, the button should be disabled, but again it will be enabled.
...
const [name, setName] = useState("");
const [surname, setSurname] = useState("");
const [email, setEmail] = useState("");
const [checkbox, setCheckbox] = useState(false);
let handleSubmit = async (e) => {
e.preventDefault();
try {
...
}
};
return(
<Input
required
type="text"
value={name}
placeholder="İsim"
onChange={(e) => setName(e.target.value)}
/>
<Input
required
type="text"
value={surname}
placeholder="Soyisim"
onChange={(e) => setSurname(e.target.value)}
/>
<Input
required
type="email"
placeholder="E-mail"
onChange={(e) => setEmail(e.target.value)}
/>
<Input
type="checkbox"
required
value={checkbox}
onChange={(e) => setCheckbox(e.target.value)}
/>
<input
type="submit"
name="Onaylıyorum"
disabled={!name || !surname || !email || !checkbox}
/>
For the checkbox you have to change from value prop to the checked prop and access event.target.checked instead i.e
<input type="checkbox" checked={checkbox} onChange={(e) => setCheckbox(e.target.checked)} />
The react docs have an example too
Checkboxes are special and don't have a .value, rather, you want to be looking for .checked in your checkboxes onChange function.
Like this...
onChange={(e) => setCheckbox(e.target.checked)}
I am a newbie in ReactJS and I am making a simple contact manager.
In my InputContact component I take name and email of contact and after submission I store in state variables and pass to parent.
To check my state var is updated , i check my console.
The problem is that, after I submit the form after giving data, I only see a blank line in console. After again clicking on submit, then I see my input in console.
My question is
Why I have to click submit twice , in order to see my state variable getting updated ??
My InputContact.js file
import React from 'react'
import { useState } from 'react';
const InputContact = (props)=>{
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const validateInput = (e)=>{
e.preventDefault();
setName(e.target.fname.value);
setEmail(e.target.femail.value);
console.log(name)
props.addContact(name,email);
}
return(
<>
<form onSubmit={validateInput}>
<label>Name
<input type="text" name='fname' ></input>
</label>
<br/>
<label>Email
<input type="text" name='femail' ></input>
</label>
<button type="submit">Save</button>
</form>
</>
)
};
export default InputContact;
My App.js file is
import Header from './components/Header/Header'
import InputContact from './components/InputContact/InputContact';
import { v4 as uuidv4 } from 'uuid';
function App(){
const [contacts, setContacts] = useState([]);
const addContactFn= (name,email)=>{
setContacts([...contacts, {id:uuidv4(), name:name, email:email}]);
}
return(
<>
<Header />
<InputContact addContact = {addContactFn}/>
</>
)
}
export default App; ```
Your setName call is asynchronous. You cannot guarantee that
console.log(name)
right after
setName(e.target.fname.value);
How you are using state isn't really the normal way. You want to use onChange handlers on the inputs to set the state for each name and email, e.g.
onChange={(e)=> setEmail(e.target.value)}
Then onSubmit of your form should refer to the state variables for name and email, not e.target.value
const validateInput = (e)=>{
e.preventDefault();
props.addContact(name,email);
}
To check the updated value, you can use useEffect hook as
import React from 'react'
import { useState, useEffect } from 'react';
.
.
.
useEffect(() => {
console.log('Name', name);
}, [name]);
const validateInput = (e)=>{
e.preventDefault();
setName(e.target.fname.value);
setEmail(e.target.femail.value);
props.addContact(name,email);
}
.
.
.
I do it like this, so the state updates on typing and when you send it, is already updated.
<form onSubmit={validateInput}>
<label>Name
<input type="text" name='fname' onChange={e => setName(e.target.value) ></input>
</label>
<br/>
<label>Email
<input type="text" name='femail' onChange={e => setEmail(e.target.value) ></input>
</label>
<button type="submit">Save</button>
</form>
I am working on a login page where I am using redux-form. I want to disable the submit button until email and password are filled. I tried but I am failed, could someone please help me how to achieve my goal. Thanks
Code
<form onSubmit={handleSubmit}>
<div className="sign-up-form">
<div className="space-2">
<Field
name="email"
component={renderField}
type="email"
label="Email"
/>
</div>
<div className="space-2">
<Field
name="password"
component={renderField}
type="password"
label="Password"
/>
</div>
{/* <button className='login-button' type='submit'>Login</button> */}
<div className="">
<button className="login-button" type="submit">
{loading ? (
<Loader
type="ThreeDots"
color="#ffffff"
height="10"
width="100"
/>
) : (
"Login"
)}
</button>
</div>
</div>
</form>
You can check this link handleSubmit and props:
https://redux-form.com/6.0.0-alpha.4/docs/api/props.md/
const {invalid} = this.props
return(
<button type="submit" className="send-btn"
disabled={invalid|| submitting || pristine}>
submit
</button>)
A possible way of doing this is use redux-form selectors to read the input values and return a property indicating if the button should be enabled or not.
To do so, you need to connect your form to redux state and use mapStateToProps to return the desired value.
Idea:
import { connect } from "react-redux";
import { Field, reduxForm, formValueSelector } from "redux-form";
let MyForm = props => {
const { enableSubmit } = props; // new property set from redux state
return (
<form>
... your form
</form>
}
const selector = formValueSelector("myForm"); // <-- same as form name
MyForm = connect(state => {
const hasUsername = selector(state, "email"); // read username value
const hasPassword = selector(state, "password"); // read username value
const enableSubmit = hasUsername && hasPassword; // logic for enabling the submit button
return {
enableSubmit // this will set property `enableSubmit` which you can read in your component
};
})(MyForm);
I prepared a working example here