I have a view showing name and email. I click edit, and an overlay shows up. I want to have the state updated on save changes, not on change, as to avoid having this.state.name and this.state.newName...
Not sure how to handle this...
This is the view - not editable
<div>
<span>{name}</span>
<span>{email}</span>
</div>
This is the form - editable
<form>
<div>
<span>
<input
type="text"
name="name"
title="Please fill out this field"
required
onBlur={event => { handleChange(event) }}
onChange={event => { handleChange(event) }}
/>
</span>
</div>
<div>
<span>
<input
type="text"
name="email"
title="Please fill out this field"
required
onBlur={event => { handleChange(event) }}
onChange={event => { handleChange(event) }}
/>
</span>
</div>
</form>
Related
i'm a beginner in React and trying to learn useState. and I have difficulties on how to get the value of input and to save the value and print it on button click
const HomePage = () => {
const [state, setState] = useState({
Name: "",
surName: "",
});
const handleChange = (e) => {
setState({
...state,
[e.target.name]: e.target.value,
});
};
const RenderNameOC = () => {
return (
<p>
Halo {Name} {surName}
</p>
);
};
return (
<DivContainer>
<ContainerTitle>
<p>Exercise 2 - Form</p>
</ContainerTitle>
<InputContainer>
<InputArea>
<label>Name: </label>
<input type="text" value={state.Name} onChange={handleChange} />
</InputArea>
<InputArea>
<label>Surname: </label>
<input type="text" value={state.surName} onChange={handleChange} />
</InputArea>
<SubmitButton onClick={RenderNameOC}>Submit</SubmitButton>
</InputContainer>
</DivContainer>
);
};
export default HomePage;
this is my code right now and the error it gave me was 'name' and 'surname' is not defined.
my expected result is that there will be 2 input textbox with for name and surname. and when the button is clicked, it will add a new <p> below it.
Here should be state.Name and state.surName
<p>
Halo {state.Name} {state.surName}
</p>
And add name in both inputs
<input
type="text"
name="Name"
value={state.Name}
onChange={handleChange}
/>
<label>Surname: </label>
<input
type="text"
name="surName"
value={state.surName}
onChange={handleChange}
/>
But no point of returning anything RenderNameOC since onClick is a void function. Just move this template below the submit button
Demo
import React from 'react'
export default class Login extends React.Component {
handleSubmit=(e)=>
{
e.preventDefault();
console.log('you clikked submit')
}
state={
fName:'',
lName:'',
gender:'',
}
These are the functions i am talking about
i am using setState to set the values input from the textfield.
fnameChange = (e) =>{
this.setState({fName:e.target.value})
}
lnameChange = (e) =>{
this.setState({lName:e.target.value})
}
render() {
return (
<div>
<h1>Login</h1>
<form
onSubmit={this.handleSubmit}
className='add-form' autoComplete="off">
<div className='form-control' >
These are the input fields from where i am calling the functions.
both are coded in exact same way.
I am using tags for printing the data to webpage.
I also tried console logging => onChange, the lastName textfield.
But some how onChange set for lastName textfield is getting fired when i enter value in firstName textfield.
<div>
<label >First Name</label>
<input type='text' name='firstName' onChange={this.fnameChange.bind(this)} required maxLength={10}/>
<h1>{this.state.fName}</h1>
</div>
<div>
<label >Last Name</label>
<input type='text' name='lastName' onChanege={this.lnameChange.bind(this)} required maxLength={10}/>
<h1>{this.state.lName}</h1>
</div>
<div>
<label >Email</label>
<input type='text' name='email' required />
<h1>{this.state.fName}</h1>
</div>
</div>
<div className='form-control form-control-check'>
<p><label>Male</label>
<input type='radio' name='gender' value='male' required/></p>
<p><label>Female</label>
<input type='radio' name='gender' value='female'/></p>
<p><label>Other</label>
<input type='radio' name='gender' value='other'/></p>
</div>
<div className='form-control'>
<input type='submit' value='Login'
className='btn btn-block'
/>
</div>
</form>
</div>
)
}
}
<input type='text' name='lastName' onChanege={this.lnameChange.bind(this)} required maxLength={10}/>
onChanege should be onChange
Multiple problems.
You are resetting your state on each onChange.
You had to consider the previous values and override the state like,
fnameChange = (e) => {
this.setState({...this.state, fName: e.target.value });
};
lnameChange = (e) => {
this.setState({...this.state, lName: e.target.value });
};
You don't need to bind as you are using arrow functions.
You can use the value of state to make your inputs a controlled component.
Example: https://stackblitz.com/edit/react-ts-dufrzd?file=Hello.tsx
Component with input and button to reset input TexInputComponent:
<input
type={type}
name={name}
ref={register}
/>
<button
type="button"
onClick={clearInput}>
Reset input
</button>
const clearInput = () => {
document.querySelector(`#${name}`).value = null;
};
I'm using TexInputComponent inside form in another component:
<TexInputComponent
name="title"
defaultValue={data?.title}
register={register({ required: 'Title is required.' })}
error={errors.title}
/>
Now when I click submit on form react-hook-form return me error e.g 'Title is required!'. When I writing something in TexInputComponent, then error disapear.
The problem is when I writing text and click button to reset input. The clearInput method is executed (this method changing value to null) Now should displaying error, but I thing the react hook form can't see value changing.
How I can fix it?
Your clearInput() doesn't work because you don't provide a unique id so it can't find the input element to reset. So change to this:
<input
id={name} // --> add this line to fix
type={type}
name={name}
ref={register}
/>
However there are other ways to easily reset the form without having to define your own reset method:
Use <input type='reset' /> to create a reset button that resets all fields in a form.
Use reset() function from useForm hook to reset a specific field:
const { register, reset } = useForm();
return (
<form onSubmit={handleSubmit(onSubmit)}>
<label>First name</label>
<input type="text" name="firstName" ref={register} />
<label>Last name</label>
<input type="text" name="lastName" ref={register} />
<input type="submit" />
<button
type="button"
onClick={() => reset({ firstName: "default name" })}
>
Reset first name
</button>
</form>
);
I am trying to implement simple form which triggers API call on form submit in React.
It blows my mind as when trying the below code:
import React, { Component } from 'react';
import axios from 'axios';
var panelStyle = {
'max-width': '80%',
margin: '0 auto'
}
class DBInject extends Component {
constructor() {
super();
this.formHandler = this.formHandler.bind(this);
this.state = {
formFields: {Id: '',
Name: '',
Payment: "01-10-2019",
Type: '',
Value: 110,
Cycle:'',
Frequency:''
}
}
}
render() {
return(
<div>
<div class="panel panel-primary" style={panelStyle}>
<div class="panel panel-heading">React Forum - Register</div>
<div class="panel panel-body">
<form onsubmit={this.formHandler(this.state.formFields)}>
<strong>Id:</strong> <br /> <input type="text" name="Id" placeholder="123" onChange={(e) => this.inputChangeHandler.call(this, e)} value={this.state.formFields.Id} /> <br />
<strong>Name:</strong> <br /> <input type="text" name="Name" placeholder="me#example.com" onChange={(e) => this.inputChangeHandler.call(this, e)} value={this.state.formFields.Name}/> <br />
<strong>Cycle:</strong> <br /> <input type="text" name="Cycle" placeholder="me#example.com" onChange={(e) => this.inputChangeHandler.call(this, e)} value={this.state.formFields.Cycle} /> <br />
<strong>Frequency:</strong> <br /> <input type="text" name="Frequency" onChange={(e) => this.inputChangeHandler.call(this, e)} value={this.state.formFields.Frequency}/> <br />
<strong>Type:</strong> <br /> <input type="text" name="Type" onChange={(e) => this.inputChangeHandler.call(this, e)} value={this.state.formFields.Type} /> <br />
<strong>Payment:</strong> <br /> <input type="date" name="Payment" onChange={(e) => this.inputChangeHandler.call(this, e)} value={this.state.formFields.Payment}/> <br />
<strong>Value:</strong> <br /> <input type="number" name="Value" onChange={(e) => this.inputChangeHandler.call(this, e)} value={this.state.formFields.Value}/> <br /><br />
<button class="btn btn-primary">Send to database</button>
</form>
</div>
</div>
</div>
);
}
inputChangeHandler(e) {
console.log(e);
let formFields = {...this.state.formFields};
formFields[e.target.name] = e.target.value;
this.setState({
formFields
});
};
formHandler(formFields) {
console.log(formFields);
alert('This button does nothing.');
axios.post('http://127.0.0.1:1880/api','', {headers:formFields})
.then(function(response){
console.log(response);
//Perform action based on response
})
.catch(function(error){
console.log(error);
//Perform action based on error
});
}
}
export default DBInject
formHandler gets called every time InputchangeHandler gets called - which is not my intention.
Is there any other simpler way to do it in React?
Every time you call setState the component re-renders. Your form element is calling the function every time it re-renders. You need to make the following changes:
#Update onsubmit
<form onsubmit={this.formHandler.bind(this)}>
#Reference the formFields directly from the component's state
formHandler() {
const { formFields } = this.state;
You can read more on React forms here:
https://reactjs.org/docs/forms.html
Make sure to reference state from inside the handler function rather than passing it in - as this will make your function re-render every state update.
Form element:
//make sure the "S" in submit is capitalized
<form onSubmit={this.formHandler}>
...Your Form Contents
</form>
Handler function:
formHandler(e) {
e.preventDefault() // stop propagation at the start
// reference state from here with this.state like so:
const { formFields } = this.state;
...Your handler code
}
I'm not sure what i'm doing wrong here. I'm trying to console log when i click on a button on a form element using onSubmit function.
export class Search extends Component {
state = {
text: ''
};
onFormSubmit = e => {
console.log('Working');
e.preventDefault();
};
onChange = e => this.setState({ [e.target.name]: e.target.value });
render() {
return (
<div>
<form onSubmit={this.onFormSubmit} className='form' />
<input
type='text'
onChange={this.onChange}
value={this.state.text}
name='text'
placeholder='Search Users...'
/>
<input
type='submit'
value='Search'
className='btn btn-dark btn-block'
/>
</div>
);
}
}
You are not wrapping your button in form but closing the form itself,
<form onSubmit={this.onFormSubmit} className='form' />
You need to wrap input and button in form like,
<form onSubmit={this.onFormSubmit} className='form'>
<input
type='text'
onChange={this.onChange}
value={this.state.text}
name='text'
placeholder='Search Users...'
/>
<input
type='submit'
value='Search'
className='btn btn-dark btn-block'
/>
</form> //form closing tag