My form is not reset after submit. Whats wrong ?? I am trying to set the state properties to null after submit.But the input values are not set to null. Iam not getting whats wrong with my code.Help me to solve this issue.
class AddNinja extends Component {
state = {
id: null, name: null, age: null, belt: null
};
handleChange = e => {
this.setState({[e.target.id]: e.target.value });
};
handleSubmit = e => {
e.preventDefault();
this.props.addNijna(this.state);
this.setState({id: null, name: null, age: null, belt: null });
};
render() {
return (
<div>
<h4>Add Ninja</h4>
<form onSubmit={this.handleSubmit}>
<label htmlFor="name">id : </label>
<input type="text" id="id" onChange={this.handleChange} />
<label htmlFor="name">Name : </label>
<input type="text" id="name" onChange={this.handleChange} />
<label htmlFor="age">Age : </label>
<input type="text" id="age" onChange={this.handleChange} />
<label htmlFor="belt">Belt : </label>
<input type="text" id="belt" onChange={this.handleChange} />
<button type="submit" className="btn btn-secondary btn-sm m-2">
Submit
</button>
</form>
</div>
);
}
}
export default AddNinja;
You need your inputs to be controlled, meaning they get their value from state and onChange since the state is changed it is reflected in your component. Also set the values to an empty string instead of null to avoid switching from uncontrolled to controlled components at runtime.
You can learn more about about controlled inputs here: https://reactjs.org/docs/forms.html
As for your code what you need to do is:
class AddNinja extends Component {
state = {
id: null, name: null, age: null, belt: null
};
handleChange = e => {
this.setState({[e.target.id]: e.target.value });
};
handleSubmit = e => {
e.preventDefault();
this.props.addNijna(this.state);
this.setState({id: null, name: null, age: null, belt: null });
};
render() {
const {id, name, age, belt} = this.state;
return (
<div>
<h4>Add Ninja</h4>
<form onSubmit={this.handleSubmit}>
<label htmlFor="name">id : </label>
<input value={id} type="text" id="id" onChange={this.handleChange} />
<label htmlFor="name">Name : </label>
<input value={name} type="text" id="name" onChange={this.handleChange} />
<label htmlFor="age">Age : </label>
<input value={age} type="text" id="age" onChange={this.handleChange} />
<label htmlFor="belt">Belt : </label>
<input value={belt} type="text" id="belt" onChange={this.handleChange} />
<button type="submit" className="btn btn-secondary btn-sm m-2">
Submit
</button>
</form>
</div>
);
}
}
export default AddNinja;
Related
I have some data and form inputs, I need to prefill the existing data in the fields and when click on edit I like to edit the data and submit it to the state on button click
const data = {
name: "nazar",
email: "nazar#gmail.com",
phone: 123456789
};
const [ editData, setEditData ] = useState()
function handleEdit(){
}
function handleSubmit(){
}
<form onChange={handleEdit}>
<input type="text" name='name'/><button>Edit</button><br/>
<input type="text" name='email'/><button>Edit</button><br/>
<input type="text" name='phone'/><button>Edit</button><br/>
<button type='submit' onSubmit={handleSubmit}>Submit</button>
</form>
// declare your data as initial state
const [data, setData] = React.useState({
name: 'nazar',
email: 'nazar#gmail.com',
phone: 123456789,
});
// handle on change according to input name and setState
const handleChange = (e) => {
setData({ ...data, [e.target.name]: e.target.value });
};
const handleSubmit = (e) => {
e.preventDefault()
// take data to submit
};
return (
<div>
<form onSubmit={handleSubmit}>
<input
type="text"
name="name"
value={data.name} // inject state correspond to input and so on
onChange={handleChange}
/>
<button>Edit</button>
<br />
<input
type="text"
name="email"
value={data.email}
onChange={handleChange}
/>
<button>Edit</button>
<br />
<input
type="text"
name="phone"
value={data.phone}
onChange={handleChange}
/>
<button>Edit</button>
<br />
<button type="submit">
Submit
</button>
</form>
</div>
);
I'd like to write an unordered list compiled from a form's input values into a <ul> when I click on the Submit button. It's a controlled form in a class based component. Unfortunately I haven't found out how I can achieve it without hooks.
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
name: "",
email: "",
message: "",
demo: "",
};
this.changeHandler = this.changeHandler.bind(this);
this.submitFormHandler = this.submitFormHandler.bind(this);
}
changeHandler = (e) => {
this.setState = {
name: e.target.value,
email: e.target.value,
message: e.target.value,
demo: `
<li>${this.state.name}</li>
<li>${this.state.email}</li>
<li>${this.state.message}</li> `
};
this.setState(this.setState)
};
submitFormHandler = (e) => {
e.preventDefault();
// I guess the solution will be here somehow
};
render() {
return (
<form onSubmit={this.submitFormHandler} >
<label htmlFor="name">Name:</label> <br/>
<input id="name" type="text" value={this.state.name} onChange={this.changeHandler} />
<br/>
<label htmlFor="mail">E-mail:</label> <br/>
<input id="mail" type="email" value={this.state.email} onChange={this.changeHandler} />
<br/>
<label htmlFor="msg">Message:</label> <br/>
<textarea id="msg" type="email" value={this.state.message} onChange={this.changeHandler} />
<h4>Values of the inputs:</h4>
<ul id="demo">
{this.state.demo} {/* the list would be here! */}
</ul>
<button type="submit">Submit</button>
</form>
); }
};
To show something when it is submitted I would make a isSubmitted flag. Also you controlled inputs were not working. When inputs ids are corresponding with names in state we can easier handle them in onChange handler function. Also when it is submitted we can prevent user from updating data in changeHandler with early return. So I fixed it in code below:
// import React from 'react';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
name: '',
email: '',
message: '',
isSubmitted: false,
};
this.changeHandler = this.changeHandler.bind(this);
this.submitFormHandler = this.submitFormHandler.bind(this);
}
changeHandler = ({ target }) => {
if (this.state.isSubmitted) return;
this.setState({ [target.id]: target.value });
};
submitFormHandler = (e) => {
e.preventDefault();
this.setState({ isSubmitted: true });
};
render() {
return (
<div>
<form onSubmit={this.submitFormHandler}>
<label htmlFor="name">Name:</label> <br />
<input
id="name"
type="text"
value={this.state.name}
onChange={this.changeHandler}
/>
<br />
<label htmlFor="email">E-mail:</label> <br />
<input
id="email"
type="email"
value={this.state.email}
onChange={this.changeHandler}
/>
<br />
<label htmlFor="message">Message:</label> <br />
<textarea
id="message"
type="email"
value={this.state.message}
onChange={this.changeHandler}
/>
<br />
<button type="submit">Submit</button>
</form>
{this.state.isSubmitted && (
<React.Fragment>
<h4>Values of the inputs:</h4>
<ul>
<li>{this.state.name}</li>
<li>{this.state.email}</li>
<li>{this.state.message}</li>
</ul>
</React.Fragment>
)}
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>
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
I want to not loose my other states, when changing one in functional component. I know how to do it in class components, but how you do it in functional? Class component this.setState({...this.state, somestate: somestate});
My Functional component looks like this now:
const [product, setProduct] = useState({});
let { id } = useParams();
useEffect(() => {
let productFromLocalStorage = localStorage[id];
setProduct(JSON.parse(productFromLocalStorage));
}, [id]);
function handleName(event) {
setProduct({name: event.target.value});
// setName(event.target.value);
}
return (
<div style={styles.container}>
<h1 style={styles.title}>Product {product.name} Edit Page</h1>
<form style={styles.form} onSubmit={handleSave}>
<label style={styles.label}>
Name: <input value={product.name} type="text" onChange={handleName}></input>
</label>
<label style={styles.label}>
EAN: <input value={product.ean} type="text" onChange={handleEan}></input>
</label>
<label style={styles.label}>
Type: <input value={product.type} type="text" onChange={handleType}></input>
</label>
<label style={styles.label}>
Weight:{' '}
<input value={product.weight} type="text" onChange={handleWeight}></input>
</label>
<label style={styles.label}>
Color:{' '}
<input value={product.color} type="text" onChange={handleColor}></input>
</label>
<label style={styles.label}>
Active:{' '}
<input value={product.active} type="checkbox" onChange={handleActive}></input>
</label>
<input style={styles.submitButton} type="submit" value="SAVE"></input>
</form>
</div>
);
function handleSave(event) {
const productInfo = {
name: product.name,
ean: product.ean,
type: product.type,
weight: product.weight,
color: product.color,
active: product.active,
};
localStorage.setItem(id, JSON.stringify(productInfo));
alert('Product: ' + name + ' edited!');
}
my product state has other params like weight and etc... when I am setting setProduct({name: event.target.value}); other values gets empty. How to solve it?
what you are doing is overriding so like you said you need to keep current values so do this:
setProduct({...product, name: event.target.value})
You can do the same via useState() also,
const [product, setProduct] = useState({});
someHandler=(event)=>(
setProduct(product=>{
...product,
name:event.target.value
});
)
I am trying to type on the inputs but it is not allowing me too. My state changes but it doesn't show.
I am using props to show an event OR and empty event if there is no props (no event selected).
Im sorry but Stack is telling me to add more details but I don't know what else to add, I already described my problem
class EventForm extends PureComponent {
state = {
event: this.props.selectedEvt,
query: ""
};
onFormSubmit = e => {
e.preventDefault();
this.props.addEvent(this.state.event);
};
onInputChange = evt => {
console.log(evt);
evt.persist();
let newEvt = this.state.event;
newEvt[evt.target.name] = evt.target.value;
this.setState({
event: newEvt
});
};
componentDidUpdate(prevProps) {
this.props.selectedEvt &&
this.setState({
event: this.props.selectedEvt
});
}
render() {
const { event } = this.state;
return (
<form className="card" onSubmit={this.onFormSubmit}>
<div className="form-row card-body">
<div className="form-group col-md-12">
<label hmtlfor="inputName">Event Name</label>
<input
name="title"
type="text"
className="form-control"
id="inputEventName"
onChange={this.onInputChange}
value={event.title}
/>
<label hmtlfor="inputDate">Event Date</label>
<input
name="date"
type="date"
className="form-control"
id="inputEventDate"
onChange={this.onInputChange}
value={event.date}
/>
<label hmtlfor="inputDate">Event Time</label>
<input
name="time"
type="time"
className="form-control"
id="inputEventTime"
onChange={this.onInputChange}
value={event.time}
/>
<label hmtlfor="inputAddress">Address</label>
<input
name="address"
type="text"
className="form-control"
id="autocomplete"
onChange={this.onInputChange}
value={event.address}
autoComplete="new-password"
/>
<label hmtlfor="inputHost">Hosted By</label>
<input
name="host"
type="text"
className="form-control"
id="inputHost"
onChange={this.onInputChange}
value={event.host}
/>
<label hmtlfor="inputDesc">Description</label>
<textarea
name="desc"
className="form-control"
rows="5"
id="inputDesc"
wrap="soft"
onChange={this.onInputChange}
value={event.description}
/>
<button type="submit" className="btn btn-primary mt-2">
Submit
</button>
</div>
</div>
</form>
);
}
}
export default EventForm;
Every time input value change componentDidMount run and you reset state to initial state value in componentDidUpdate.
componentDidUpdate(prevProps) {
this.props.selectedEvt &&
this.setState({
event: this.props.selectedEvt // Here is the problem
});
}
Also You mutate state when input change. And because its pureComponent it will not update.
Change onInputChange to
onInputChange = evt => {
let name = evt.target.name;
let value = evt.target.value;
let newEvent = {...this.state.event};
newEvent[name] = value
this.setState({event: newEvent});
}