setState not working after submit but data is updated in database - reactjs

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);
}

Related

React input box no longer works

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.

Why won't a React form register inputs on only 3 fields?

This form I'm doing in a React app was working fine until I added a few more fields. I can't figure out why I wouldn't be able to type into "first Name", "middle", or "last name" on the form.
Basically, I've tried adding the fields with the exact process that I added the other fields with, but it's just not working and I keep looking over the code and can't find out what's going on. I add everything throughout the code that all the other fields have.
import React, { Component } from 'react';
import { Link, withRouter } from 'react-router-dom';
import { compose } from 'recompose';
import { withFirebase } from '../Firebase';
import * as ROUTES from '../../constants/routes';
import * as ROLES from '../../constants/roles';
const SignUpPage = () => (
<div>
<h1>SignUp</h1>
<SignUpForm />
</div>
);
const INITIAL_STATE = {
username: '',
firstName: '',
middleName: '',
lastName: '',
email: '',
passwordOne: '',
passwordTwo: '',
isAdmin: false,
mailingAddress: '',
city: '',
state: '',
zip: '',
error: null,
};
class SignUpFormBase extends Component {
constructor(props) {
super(props);
this.state = { ...INITIAL_STATE };
}
onChange = event => {
this.setState({ [event.target.name]: event.target.value });
};
onSubmit = event => {
const { username, firstName, middleName, lastName, email, passwordOne, isAdmin, mailingAddress, city, state, zip } = this.state;
const roles = {};
if (isAdmin) {
roles[ROLES.ADMIN] = ROLES.ADMIN;
}
this.props.firebase
.doCreateUserWithEmailAndPassword(email, passwordOne)
.then(authUser => {
// Create a user in your Firebase realtime database
return this.props.firebase
.user(authUser.user.uid)
.set({
username,
firstName,
middleName,
lastName,
email,
roles,
mailingAddress,
city,
state,
zip,
});
})
.then(() => {
return this.props.firebase.doSendEmailVerification();
})
.then(() => {
this.setState({ ...INITIAL_STATE });
this.props.history.push(ROUTES.HOME);
})
.catch(error => {
this.setState({ error });
});
event.preventDefault();
}
onChangeCheckbox = event => {
this.setState({ [event.target.name]: event.target.checked });
};
onChangeSelection = event => {
this.setState({ [event.target.name]: event.target.selected });
};
render() {
const {
username,
firstName,
middleName,
lastName,
email,
passwordOne,
passwordTwo,
isAdmin,
mailingAddress,
city,
state,
zip,
error,
} = this.state;
const isInvalid =
passwordOne !== passwordTwo ||
passwordOne === '' ||
username === '' ||
email === '' ||
firstName === '' ||
lastName === ''||
mailingAddress === '' ||
city === '' ||
state === '' ||
zip === '';
return (
<form onSubmit={this.onSubmit}>
<div class="form-row">
<div class="form-group col-md-4">
<input
name="username"
value={username}
onChange={this.onChange}
type="text"
placeholder="Username"
class="form-control"
/>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-4">
<input
name="firstname"
value={firstName}
onChange={this.onChange}
type="text"
placeholder="First Name"
class="form-control"
/>
</div>
<div class="form-group col-md-4">
<input
name="middlename"
value={middleName}
onChange={this.onChange}
type="text"
placeholder="Middle Name"
class="form-control"
/>
</div>
<div class="form-group col-md-4">
<input
name="lastname"
value={lastName}
onChange={this.onChange}
type="text"
placeholder="Last Name"
class="form-control"
/>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-12">
<input
name="email"
value={email}
onChange={this.onChange}
type="text"
placeholder="Email Address"
class="form-control"
/>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-6">
<input
name="passwordOne"
value={passwordOne}
onChange={this.onChange}
type="password"
placeholder="Password"
class="form-control"
/>
</div>
<div class="form-group col-md-6">
<input
name="passwordTwo"
value={passwordTwo}
onChange={this.onChange}
type="password"
placeholder="Confirm Password"
class="form-control"
/>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-2">
<label>
Admin:
<input
name="isAdmin"
type="checkbox"
checked={isAdmin}
onChange={this.onChangeCheckbox}
/>
</label>
</div>
</div>
<br />
<div class="form-row">
<div class="form-group col-md-4">
Mailing Address:
<input
name="mailingAddress"
value={mailingAddress}
onChange={this.onChange}
type="text"
placeholder="Street Address"
class="form-control"
/>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-4">
<input
name="city"
value={city}
onChange={this.onChange}
type="text"
placeholder="City"
class="form-control"
/>
</div>
<div class="form-group col-md-2">
<select id="inputState" class="form-control" value={state} onChange={this.onChangeSelection}>
<option selected>Choose a state</option>
<option>...</option>
</select>
</div>
<div class="form-group col-md-1">
<input
name="zip"
value={zip}
onChange={this.onChange}
type="text"
placeholder="Zip Code"
class="form-control"
/>
</div>
</div>
<button disabled={isInvalid} type="submit" class="btn btn-primary">
Sign Up
</button>
{error && <p>{error.message}</p>}
</form>
);
}
}
const SignUpLink = () => (
<p>
Don't have an account? <Link to={ROUTES.SIGN_UP}>Sign Up</Link>
</p>
);
const SignUpForm = compose(
withRouter,
withFirebase,
)(SignUpFormBase);
export default SignUpPage;
export { SignUpForm, SignUpLink };
I just want the name fields to register keystrokes like the rest of the form can. Everything else works. I don't get why first, middle, and last name will only focus.
Try changing value to defaultValue. defaultValue only gets set on initial load for a form. After that, it won't get "naturally" updated because the intent was only to set an initial default value.
import React, { Component } from 'react';
import { Link, withRouter } from 'react-router-dom';
import { compose } from 'recompose';
import { withFirebase } from '../Firebase';
import * as ROUTES from '../../constants/routes';
import * as ROLES from '../../constants/roles';
const SignUpPage = () => (
<div>
<h1>SignUp</h1>
<SignUpForm />
</div>
);
const INITIAL_STATE = {
username: '',
firstName: '',
middleName: '',
lastName: '',
email: '',
passwordOne: '',
passwordTwo: '',
isAdmin: false,
mailingAddress: '',
city: '',
state: '',
zip: '',
error: null,
};
class SignUpFormBase extends Component {
constructor(props) {
super(props);
this.state = { ...INITIAL_STATE };
}
onChange = event => {
this.setState({ [event.target.name]: event.target.value });
};
onSubmit = event => {
const { username, firstName, middleName, lastName, email, passwordOne, isAdmin, mailingAddress, city, state, zip } = this.state;
const roles = {};
if (isAdmin) {
roles[ROLES.ADMIN] = ROLES.ADMIN;
}
this.props.firebase
.doCreateUserWithEmailAndPassword(email, passwordOne)
.then(authUser => {
// Create a user in your Firebase realtime database
return this.props.firebase
.user(authUser.user.uid)
.set({
username,
firstName,
middleName,
lastName,
email,
roles,
mailingAddress,
city,
state,
zip,
});
})
.then(() => {
return this.props.firebase.doSendEmailVerification();
})
.then(() => {
this.setState({ ...INITIAL_STATE });
this.props.history.push(ROUTES.HOME);
})
.catch(error => {
this.setState({ error });
});
event.preventDefault();
}
onChangeCheckbox = event => {
this.setState({ [event.target.name]: event.target.checked });
};
onChangeSelection = event => {
this.setState({ [event.target.name]: event.target.selected });
};
render() {
const {
username,
firstName,
middleName,
lastName,
email,
passwordOne,
passwordTwo,
isAdmin,
mailingAddress,
city,
state,
zip,
error,
} = this.state;
const isInvalid =
passwordOne !== passwordTwo ||
passwordOne === '' ||
username === '' ||
email === '' ||
firstName === '' ||
lastName === ''||
mailingAddress === '' ||
city === '' ||
state === '' ||
zip === '';
return (
<form onSubmit={this.onSubmit}>
<div class="form-row">
<div class="form-group col-md-4">
<input
name="username"
defaultValue={username}
onChange={this.onChange}
type="text"
placeholder="Username"
class="form-control"
/>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-4">
<input
name="firstname"
defaultValue={firstName}
onChange={this.onChange}
type="text"
placeholder="First Name"
class="form-control"
/>
</div>
<div class="form-group col-md-4">
<input
name="middlename"
value={middleName}
onChange={this.onChange}
type="text"
placeholder="Middle Name"
class="form-control"
/>
</div>
<div class="form-group col-md-4">
<input
name="lastname"
defaultValue={lastName}
onChange={this.onChange}
type="text"
placeholder="Last Name"
class="form-control"
/>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-12">
<input
name="email"
value={email}
onChange={this.onChange}
type="text"
placeholder="Email Address"
class="form-control"
/>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-6">
<input
name="passwordOne"
value={passwordOne}
onChange={this.onChange}
type="password"
placeholder="Password"
class="form-control"
/>
</div>
<div class="form-group col-md-6">
<input
name="passwordTwo"
value={passwordTwo}
onChange={this.onChange}
type="password"
placeholder="Confirm Password"
class="form-control"
/>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-2">
<label>
Admin:
<input
name="isAdmin"
type="checkbox"
checked={isAdmin}
onChange={this.onChangeCheckbox}
/>
</label>
</div>
</div>
<br />
<div class="form-row">
<div class="form-group col-md-4">
Mailing Address:
<input
name="mailingAddress"
value={mailingAddress}
onChange={this.onChange}
type="text"
placeholder="Street Address"
class="form-control"
/>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-4">
<input
name="city"
value={city}
onChange={this.onChange}
type="text"
placeholder="City"
class="form-control"
/>
</div>
<div class="form-group col-md-2">
<select id="inputState" class="form-control" value={state} onChange={this.onChangeSelection}>
<option selected>Choose a state</option>
<option>...</option>
</select>
</div>
<div class="form-group col-md-1">
<input
name="zip"
value={zip}
onChange={this.onChange}
type="text"
placeholder="Zip Code"
class="form-control"
/>
</div>
</div>
<button disabled={isInvalid} type="submit" class="btn btn-primary">
Sign Up
</button>
{error && <p>{error.message}</p>}
</form>
);
}
}
const SignUpLink = () => (
<p>
Don't have an account? <Link to={ROUTES.SIGN_UP}>Sign Up</Link>
</p>
);
const SignUpForm = compose(
withRouter,
withFirebase,
)(SignUpFormBase);
export default SignUpPage;
export { SignUpForm, SignUpLink };

An error occurs when trying to show an image using the "img" tag in react

This is my code. The image can be found at the path provided by this.state.imagepath but an error is showing.
<*img src={require("./upload/"+this.state.imagepath)} alt={<div>Please select an image to preview</div>}/>
//this is my component
import React, { Component } from 'react';
class Edit extends Component {
constructor(props){
super(props);
this.state={
itemid:this.props.match.params.id,
mitemid:"",
itemname:"",
qty:null,
price:null,
imagepath:""
}
this.onIDValueChange=this.onIDValueChange.bind(this);
this.onNameValueChange=this.onNameValueChange.bind(this);
this.onQtyValueChange=this.onQtyValueChange.bind(this);
this.onPriceValueChange=this.onPriceValueChange.bind(this);
this.handleSubmit=this.handleSubmit.bind(this);
this.handleImage=this.handleImage.bind(this);
}
onIDValueChange (event) {
event.preventDefault();
this.setState({
mitemid: event.target.value
});
}
onNameValueChange (event) {
event.preventDefault();
this.setState({
itemname: event.target.value
});
}
onQtyValueChange (event) {
event.preventDefault();
this.setState({
qty: event.target.value
});
}
onPriceValueChange (event) {
event.preventDefault();
this.setState({
price: event.target.value
});
}
componentDidMount(){
const item ={
itemid: this.state.itemid
}
fetch('http://localhost:4000/index/retrieveone',{
method:"POST",
headers: {
"Content-Type": "application/json"
},
body:JSON.stringify(item)
})
.then(response => response.json())
.then((res) => {
this.setState({
itemname:res.itemname,
mitemid:res.itemid,
qty:res.qty,
price:res.price,
imagepath:res.imagepath
});
})
}
handleSubmit(){
fetch('http://localhost:4000/index/foodupdate/'+this.state.itemid,{
method:"POST",
headers: {
"Content-Type": "application/json"
},
body:JSON.stringify({
itemname:this.state.itemname,
itemid:this.state.itemid,
qty:this.state.qty,
price:this.state.price,
})
})
.then(response => response.json())
}
handleImage(){
return <img src={require("./upload/"+this.state.imagepath)} alt="No image to preview"/>;
}
render() {
return (
<div className="container">
<div>
<hr/>
<div style={{backgroundColor:"#FFF0F5" }}>
<div className="form-group" >
<label className="col-lg-3 control-label">Item ID:</label>
<div className="col-lg-8">
<input className="form-control" type="text" value={this.state.mitemid} onChange={this.onIDValueChange} />
</div>
</div>
<div className="form-group">
<label className="col-lg-3 control-label">Item name:</label>
<div className="col-lg-8">
<input className="form-control" type="text" value={this.state.itemname} onChange={this.onNameValueChange}/>
</div>
</div>
<div className="form-group">
<label className="col-lg-3 control-label">Price (Rs):</label>
<div className="col-lg-8">
<input className="form-control" type="text" value={this.state.price} onChange={this.onPriceValueChange}/>
</div>
</div>
<div class="form-group">
<label className="col-lg-3 control-label">Available Quantity:</label>
<div className="col-lg-8">
<input className="form-control" type="text" value={this.state.qty} onChange={this.onQtyValueChange}/>
</div>
</div>
<div className="form-group">
<label className=" control-label"></label>
<button type="button" className="btn btn-danger btn-sm" style={{margin:"20px" }} onClick={this.handleSubmit} >
<span className="glyphicon glyphicon-trash"></span> Update
</button>
</div>
<div className="imgPreview">
{this.handleImage}
</div>
<div className="form-group">
<label className=" control-label"></label>
<button type="button" className="btn btn-info btn-sm" style={{margin:"20px" }} >
Change Image
</button>
</div>
</div>
</div>
</div>
);
}
}
export default Edit;
I have made this mistake myself. Quite frankly, dynamically rendering images in ReactJS takes a little bit of finesse (very annoying).
Your current code does not work because it does not know what this.state.imagepath means. The require method can only read a string. So, if you want to inject a variable you have to try using a string literal.
render() {
const { imagepath } = this.state;
return (
...
<img src={require(`./upload/${imagepath}`)} alt={"please select an image..."} /> etc.
Assuming the imagepath is the actual path. Also, your ./upload/... has to be exact. Make sure upload is actually within your current directory. To be sure just right click your upload directory and select copy relative path. Paste that in your require string literal.
Hope this helps.

Input text in react form component does not allow text entry

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

Reactjs - Form validation

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>
);
}
}

Resources