I am new to react and when I change my state from just variables to an object the input box no longer works.
The following code works
class AddMovie extends Component {
state = {
title: "",
watched: ""
}
onChangeMovie = (e) => {
this.setState({[e.target.name] : e.target.value});
}
uploadMovie = (e) => {
e.preventDefault();
this.props.addMovie(this.state.title, this.state.watched);
this.setState({title: "", watched: ""})
}
render(){
return (
<form onSubmit={this.uploadMovie}>
<div className="form-group">
<label>Movie Title</label>
<input type="text" className="form-control" placeholder="Enter title"
name="title" value={this.state.title} onChange={this.onChangeMovie}/>
</div>
<div className="form-group">
<label>Date Watched</label>
<input type="date" className="form-control"
name="watched" value={this.state.watched} onChange={this.onChangeMovie}/>
</div>
<button type="submit" className="btn btn-primary">Submit</button>
</form>
)
}
}
export default AddMovie;
When I change the state to an object
state ={
movieUpload: {
title: "",
watched: ""
}
}
and I change the form to add the object
render(){
return (
<form onSubmit={this.uploadMovie}>
<div className="form-group">
<label>Movie Title</label>
<input type="text" className="form-control" placeholder="Enter title"
name="title" value={this.state.movieUpload.title} onChange={this.onChangeMovie}/>
</div>
<div className="form-group">
<label>Date Watched</label>
<input type="date" className="form-control"
name="watched" value={this.state.movieUpload.watched} onChange={this.onChangeMovie}/>
</div>
<button type="submit" className="btn btn-primary">Submit</button>
</form>
)
}
The input box no longer works. Why is this and how do I change it?
If you're going to make those changes, you need to change your onChangeMovie as well
onChangeMovie = (e) => {
this.setState({uploadMovie: {...this.state.uploadMovie, [e.target.name] : e.target.value}});
}
This will copy the current this.state.uploadMovie and then overwrite the title/watched.
Related
I am new to react and Im working on reactjs with laravel api.
I designed a form using reactjs and plan on submitting the data of the form to phpmyadmin database using laravel as the api.
The problem is if I submit the data, I use setState to empty the form data, but it doesnt; but the data gets entered into the phpmyadmin database. I even try to log the response from the api to the console, but there is no message on the console of the browser.
Here is my code on the react end:
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import axios from 'axios';
class Addstudent extends Component {
state = {
name: '',
course: '',
email: '',
phone: '',
};
handleInput = (e) => {
this.setState({
[e.target.name]: e.target.value,
});
};
saveStudent = async (e) => {
e.preventDefault();
const res = await axios.post(
'http://localhost:8000/api/add-student',
this.state
);
if (res.data.status === 200) {
console.log(res.data.message);
this.setState({
name: '',
course: '',
email: '',
phone: '',
});
}
};
render() {
return (
<div className="container">
<div className="row">
<div className="col-md-12">
<div className="card">
<div className="card">
<div className="card-header">
<h4>Add Students</h4>
<Link to={'/'} className="btn btn-primary btn-sm float-end">
Back
</Link>
</div>
<div className="card-body">
<form onSubmit={this.saveStudent}>
<div className="form-group mb-3">
<label>Student Name</label>
<input
type="text"
name="name"
onChange={this.handleInput}
className="form-control"
placeholder="Enter Name"
value={this.state.name}
></input>
</div>
<div className="form-group mb-3">
<label>Student Course</label>
<input
type="text"
name="course"
onChange={this.handleInput}
className="form-control"
placeholder="Enter Course"
value={this.state.course}
></input>
</div>
<div className="form-group mb-3">
<label>Student Email</label>
<input
type="text"
name="email"
onChange={this.handleInput}
className="form-control"
placeholder="Enter Email"
value={this.state.email}
></input>
</div>
<div className="form-group mb-3">
<label>Student Phone</label>
<input
type="text"
name="phone"
onChange={this.handleInput}
className="form-control"
placeholder="Enter Phone"
value={this.state.phone}
></input>
</div>
<div className="form-group mb-3">
<button type="submit" className="btn btn-primary">
Save Student
</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
}
export default Addstudent;
On the Laravel end Here is the code on the controller handling the post request:
<?php
namespace App\Http\Controllers\API;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\Student;
class StudentController extends Controller
{
public function store(Request $request){
$student = new Student;
$student->name =$request->input('name');
$student->course =$request->input('course');
$student->email =$request->input('email');
$student->phone =$request->input('phone');
$student->save();
return response()->json([
'status'=> '200',
'message'=>'Student Added Successfully',
]);
}
}
Your handleInput function is overwriting your state with only one property, you have to keep the old data:
this.setState(s => ({
...s,
[e.target.name]: e.target.value,
}));
Otherwise you will never send all values to the API, assuming it is working correctly there
if (res.data.status === 200) {
console.log(res.data.message);
This logging is great if everything works well, but you may want to log if things go wrong too, so you could notice that you're not sending all values to the database:
try {
const res = await axios.post(
'http://localhost:8000/api/add-student',
this.state
);
// ... code using res
} catch(e) {
console.error(e);
}
I want to clear the input field after upload and submit the form.
I have checked couple of documentation, where its said after submitting the form I can return the initial state.
Here is my code
state = {
firstname: "",
lastname: "",
email: "",
file: null
};
onDrop = e => {
this.setState({ file: e.target.files[0] });
console.log({ file: e.target.files[0] });
};
handleChange = e => {
this.setState({ [e.target.id]: e.target.value });
};
handleSubmit = async e => {
e.preventDefault();
console.log(this.state);
const formData = new FormData();
formData.append("file", this.state.file);
formData.append("upload_preset", process.env.REACT_APP_UPLOAD_PRESET);
const response = await axios.post(
`https://api.cloudinary.com/v1_1/${process.env.REACT_APP_CLOUD_NAME}/image/upload`,
formData
);
await this.props.addPerson({
variables: {
firstname: this.state.firstname,
lastname: this.state.lastname,
email: this.state.email,
image: response.data.url
},
refetchQueries: [{ query: getperson }]
});
this.setState({ firstname: " ", lastname: "", email: " ", file: null }); **this is where i retutn the initial state after submitting the form, but it did not work**
};
This is my form setup
<React.Fragment>
<div>
<form id="addPerson" onSubmit={this.handleSubmit}>
<div className="field">
<label> Firstname </label>
<input type="text" id="firstname" onChange={this.handleChange} />
</div>
<div className="field">
<label> Lastname </label>
<input type="text" id="lastname" onChange={this.handleChange} />
</div>
<div className="field">
<label> Email </label>
<input type="email" id="email" onChange={this.handleChange} />
</div>
<input type="file" onChange={this.onDrop} />
<button>Add Person</button>
</form>
</div>
</React.Fragment>
It doesn't work because your inputs are not fully controlled by react, If you want to control these inputs, you need to specify the value attribute like this :
<input type="text" id="firstname" value={this.state.firstname} onChange={this.handleChange}/>
<input type="text" id="lastname" value={this.state.lastname} onChange={this.handleChange}/>
Note that the file input is always uncontrolled in react (see the documentation), so you need to reset it manually by using a reference :
constructor() {
this.fileRef = React.createRef();
...
}
handleSubmit = async e => {
// Reset the file input
this.fileRef.current.value = '';
};
render() {
...
<input type="file" ref={this.fileRef} onChange={this.onDrop} />
...
}
You haven't set the value attribute in html input with state value.
Since the value attribute is set on our form element, the displayed value will always be this.state.value, making the React state the source of truth.
Since handleChange runs on every keystroke to update the React state, the displayed value will update as the user types.
With a controlled component, every state mutation will have an associated handler function. This makes it straightforward to modify or validate user input.
For more details please check here.
Use following code,
<React.Fragment>
<div>
<form id="addPerson" onSubmit={this.handleSubmit}>
<div className="field">
<label> Firstname </label>
<input type="text" id="firstname" value={this.state.firstname} onChange={this.handleChange} />
</div>
<div className="field">
<label> Lastname </label>
<input type="text" id="lastname" value={this.state.lastname} onChange={this.handleChange} />
</div>
<div className="field">
<label> Email </label>
<input type="email" id="email" value={this.state.email} onChange={this.handleChange} />
</div>
<input type="file" onChange={this.onDrop} />
<button>Add Person</button>
</form>
</div>
</React.Fragment>
Hope this will help you !!!
We're trying to set up a data entry form that adds input to an object in mongo. We're positive this has to do with our front end as we can't get the input data to even print to an alert.
import { Panel, Button,ButtonToolbar} from 'react-bootstrap';
export default class ResearcherPortal extends React.Component {
constructor(props){
super(props);
this.state = {
schoolName: '',
studyName: '',
studyDescription: '',
identifier: '',
numberOfConsenting: null,
numberOfNonconsenting: null
},
this.handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit(event){
this.setState({numberOfConsenting: event.target.value});
alert(this.state.numberOfConsenting);
}
render() {
return (
<div className="jumbotron">
<div className="container ">
<div className ="row justify-content-md-center">
<Panel bsStyle="primary">
<Panel.Heading>
<h2>Researcher Portal</h2>
</Panel.Heading>
<Panel.Body>
<form id="Account Creation" action={"/researcherPortal"} method="POST">
<div className="form-group">
<input type="text" className="form-control" id="schoolName" placeholder="School Name"/>
</div>
<div className="form-group">
<input type="text" className="form-control" id="studyName" placeholder="Study Name"/>
</div>
<div className="form-group">
<input type="text" className="form-control" id="studyDescription" placeholder="Study Description"/>
</div>
<div className="form-group">
<input type="text" className="form-control" id="identifier" placeholder="Unique Identifier"/>
</div>
<div className="form-group">
<input type="text" className="form-control" id="numberOfConsenting" placeholder="Number of Consenting Students" value={this.state.numberOfConsenting}/>
</div>
<div className="form-group">
<input type="text" className="form-control" id="numberOfNonconsenting" placeholder="Number of Nonconsenting Students"/>
</div>
<Button type="submit" className="btn btn-primary" onClick={this.handleSubmit.bind(this)}>Create Accounts</Button>
</form>
</Panel.Body>
</Panel>
</div>
</div>
</div>
);
}
}
Expected result is the input for "Number of Consenting Students", however we are just outputting the initial constructor value.
You need to provide an onChange to the input whose value is this.state.numberOfConsenting. Something like -
changeNumberOfConsenting(event) {
this.setState({ numberOfConsenting: event.target.value });
}
...
<input ... value={this.state.numberOfConsenting} onChange={this.changeNumberOfConsenting} />
and then bind it in your constructor like you did for handleSubmit.
Use refs.
Add handler to constructor:
this.consentingStudents = React.createRef();
Add this ref for needed input:
<input type="text" className="form-control" id="numberOfConsenting" placeholder="Number of Consenting Students" ref={this.consentingStudents} value={this.state.numberOfConsenting} />
And get its value in the handleSubmit():
handleSubmit(event) {
this.setState({ numberOfConsenting: this.consentingStudents.current.value });
alert(this.consentingStudents.current.value);
}
I'm very new to react, and following a tutorial, made this Registration form (I just changed Bootstrap html with Materialize)
import React, {Component} from 'react';
class Register extends Component {
constructor() {
super();
this.state = {
email: '',
password: '',
errors: {}
};
this.handleChange = this.handleChange.bind(this);
}
handleChange (e) {
this.setState({
[e.target.name] : e.target.value
});
}
render() {
return (
<div>
<div className="row">
<div className="col s10 m6 offset-s1 offset-m3 ">
<form className="col s12 myform">
<h3 className="center"Register </h3>
<div className="row">
<div className="input-field col s12">
<input
id="email"
type="email"
value={this.state.email}
onChange = {this.handleChange}
/>
<label htmlFor="email">Email</label>
</div>
</div>
<div className="row">
<div className="input-field col s12">
<input
id="password"
type="password"
value={this.state.password}
onChange = {this.handleChange}
/>
<label htmlFor="password">Password</label>
</div>
</div>
<button className="btn mybtn waves-effect waves-light right" type="submit" name="action">Submit
<i className="mdi-content-send right"></i>
</button>
</form>
</div>
</div>
</div>
);
}
}
export default Register;
The problem is that I can not enter anything into the form and get no error in the console. So got really preplexed. Appreciate your hints.
As you have written:
handleChange (e) {
this.setState({
[e.target.name] : e.target.value // This line I mean.
});
}
So you just need to assign name prop to input tag because you have written e.target.name and your input name is available in the state but not available in input props.
So do it like this:
- Email input
<input
name="email"
id="email"
type="email"
value={this.state.email}
onChange = {this.handleChange}
/>
- Password input
<input
name="email"
id="email"
type="email"
value={this.state.email}
onChange = {this.handleChange}
/>
I hope it will be helped you and enjoy of react
Can anybody help me, I'm really struggling with the validation form in React, I was trying also with some library but I'm doing something wrong.
I want to validate both to be required and number to be a number.
class Hello extends React.Component {
constructor() {
super();
this.state = {
firstname: '',
number: '',
};
}
onChange = (event) => {
this.setState({ [event.target.name]: event.target.value });
}
onSubmit = (event) => {
event.preventDefault();
console.log('Submited');
}
render() {
return (
<div>
<form className="form-horizontal" onSubmit={this.onSubmit}>
<div className="form-group">
<label className="col-sm-2 control-label">Name</label>
<div className="col-sm-10">
<input type="text" name="firstname" className="form-control" onChange={this.onChange} placeholder="Firstname" />
</div>
</div>
<div className="form-group">
<label className="col-sm-2 control-label">Number</label>
<div className="col-sm-10">
<input type="text" name="number" className="form-control" onChange={this.onChange} placeholder="Number" />
</div>
</div>
<div className="form-group">
<div className="col-sm-offset-2 col-sm-10">
<button type="submit" className="btn btn-success">Submit</button>
</div>
</div>
</form>
<h3>{this.state.firstname}</h3>
<h3>{this.state.number}</h3>
</div>
);
}
}