react state change doesn't work as expected - reactjs

Hi this is a code that I tried out to submit data from a form.
import * as React from 'react'
export class User extends React.Component{
constructor(props) {
super(props);
this.state = {
name: '',
message: '',
messages: ''
}
this.handleSubmit = this.handleSubmit.bind(this);
this.handleChange = this.handleChange.bind(this);
}
render() {
return (
<div class="panel panel-default" id="frame1" onSubmit={this.handleSubmit}>
<form class="form-horizontal" action="/action_page.php">
<div class="form-group">
<label class="control-label col-sm-2" for="name">Your Name </label>
<div class="col-sm-10">
<input type="text" class="form-control" name="name" placeholder="Enter your Name" onChange={this.handleChange} />
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="message">Message</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="message" placeholder="Enter your Message" onChange={this.handleChange}/>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" id="submit" class="btn btn-default">Submit</button>
</div>
</div>
</form>
</div>
);
}
handleChange(evt) {
this.setState({ [evt.target.name]: evt.target.value });
}
handleSubmit(event) {
this.setState({ messages: this.state.message });
alert('A name was submitted: ' + this.state.name + ' jjjjjj' + this.state.messages);
event.preventDefault();
}
}
As you can see in the handleSubmit(event) method, I'm setting the value of message to messages. But when I try to print messages, no value has been set. What is the mistake I'm doing here. Isn't this value need to be printed

setState is asynchronous. Try this:
handleSubmit(event) {
event.preventDefault();
this.setState({ messages: this.state.message }, () => {
alert('A name was submitted: ' + this.state.name + ' jjjjjj' + this.state.messages);
});
}
setState() does not always immediately update the component. It may batch or defer the update until later. This makes reading this.state right after calling setState() a potential pitfall. Instead, use componentDidUpdate or a setState callback (setState(updater, callback)), either of which are guaranteed to fire after the update has been applied.
https://reactjs.org/docs/react-component.html#setstate

Related

function keyword in class based component and inChange event

Can anyone please help me understand if there's any issue with the below code snippet:
import React, { Component } from "react";
class AddContactForm extends Component {
constructor() {
super();
this.state = {
name: "",
email: "",
number: ""
}
}
handleOnChange(event) {
console.log("Hi");
console.log(event.target.id);
console.log(event.target.value);
}
render() {
return (
<React.Fragment>
<div className="mx-auto">
<div class="mb-3 row">
<label for="username" class="col-sm-2 col-form-label">Name</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="username" onChange={this.handleOnChange.bind(this)}/>
</div>
</div>
<div class="mb-3 row">
<label for="mobileNumber" class="col-sm-2 col-form-label">Mobile Number</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="mobileNumber" onChange={this.handleOnChange}/>
</div>
</div>
<div class="mb-3 row">
<label for="emailId" class="col-sm-2 col-form-label">Email</label>
<div class="col-sm-10">
<input type="email" class="form-control" id="emailId" onChange={this.handleOnChange}/>
</div>
</div>
<button className="btn btn-primary w-25">Add</button>
</div>
</React.Fragment>
)
}
}
export default AddContactForm;
I am facing the problems below:
1 - unable to use function keyword with handleOnChange method
2 - none of my inputs are firing the onChange event. I am unable to get any logs in the console as added in HandleOnChange method.
Thanks.
In your constructor bind all the methods.
constructor() {
super();
this.state = {
name: "",
email: "",
number: ""
}
this.handleOnChange: this.handleOnChange.bind(this)
}
And in your inputs use like this
<input onClick={this.handleOnChange} />
You have few errors in your code aside from the one #Muhammad pointed out, some attribute names were altered in to avoid conflict for jsx so:
class became className
for became htmlFor with the label element a similar problem here.
It's also worth noting that, using arrow function is favored over using bind, so you create the function normally as an arrow function.
handleOnChange = (event) => {
console.log("Hi");
console.log(event.target.id);
console.log(event.target.value);
};
and make onChange call it.
onChange={this.handleOnChange}
You can refer for this codesandbox for a demo, you may also want to read these two questions here:
correct-use-of-arrow-functions-in-react
how-to-avoid-bind-or-inline-arrow-functions-inside-render-method

setState not working after submit but data is updated in database

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

Unable to add data from form to variable using REACT

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

React bind custom handler onChange to input

This is my SearchForm.js, it creates form with two inputs keywords and city and select list date
import React from 'react';
import ReactDOM from 'react-dom';
class SearchForm extends React.Component {
constructor(props) {
super(props)
this.state = {
keywords: '',
city: '',
date: ''
}
//this.handleChange = this.handleChange.bind(this)
//this.handleSubmit = this.handleSubmit.bind(this)
this.handleKeywordsChange = this.handleInputChange.bind(this);
}
handleKeywordsChange(event) {
console.log(1);
}
render() {
return (
<form className='form search-form' onSubmit={this.handleSubmit}>
<div class="form-row">
<div class="form-group col-md-5">
<label for="keywords">Keywords</label>
<input type="text" class="form-control" name="keywords" id="keywords" placeholder="Keywords" onChange={this.handleKeywordsChange} value={this.state.name} />
</div>
<div class="form-group col-md-5">
<label for="city">City</label>
<input type="text" class="form-control" name="city" id="city" placeholder="City" onChange={this.handleChange} value={this.state.name} />
</div>
<div class="form-group col-md-2">
<label for="date">Date</label>
<select class="form-control" name="date" id="date" onChange={this.handleChange} value={this.state.value}>
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
</select>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-12">
<input id='formButton' className='btn btn-primary' type='submit' placeholder='Send' />
</div>
</div>
</form>
)
}
}
export { SearchForm }
and I need to add different handle function to inputs like handleKeywordsChange, but there are some errors
What's wrong with my bind ?
I think there is a typo in
this.handleKeywordsChange = this.handleInputChange.bind(this);
Have you tried change it to
this.handleKeywordsChange = this.handleKeywordsChange.bind(this);
Error is because of this:
this.handleKeywordsChange = this.handleInputChange.bind(this);
You need to define handleInputChange, instead of handleKeywordsChange:
handleInputChange () {
}
Reason is as per MDN Doc:
The bind() method creates a new function that, when called, has its
this keyword set to the provided value, with a given sequence of
arguments preceding any provided when the new function is called.
So in handleKeywordsChange method you are just storing the reference of function returned by bind. So the actual function will be handleInputChange and that you need to define.

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