Value property on input field changes after a second user interaction - React - reactjs

I have a form with two input elements - one for name (type="text") and one for age (type="number"). I manage the form state in the parent component. I have my handler methods and everything set up. The form state changes when user types. Also the input value property on the name field receives its value based on the current state, but the number field does not receive it while user types but on a second interaction with the page (a click somewhere else let's say)
Here is my Form component:
const Form = (props) => {
return (
<div className="col-md-4 form">
<form id="myForm">
<div className="form-group">
<label>Please, enter your name</label>
<input onChange={props.inputChanged} id="name" type="text" className="form-control" name="name"
placeholder="Name" value={props.data.name}/>
</div>
<div className="form-group">
<label>How old are you?</label>
<input onChange={props.inputChanged} id="age" type="number" className="form-control" name="age"
placeholder="Age" value={props.data.age}/>
</div>
</div>
And the parent class based component which owns the state:
class DbControls extends Component {
//INITIAL STATE
state = {
name: '',
age: '',
greeting: 'hello',
role: 'admin'
}
//HANDLE USER INPUT FOR NAME AND AGE
inputHandler = (e) => {
if (e.target.id === 'name') {
this.setState({name: e.target.value})
} else if (e.target.id === 'age') {
this.setState({age: e.target.value})
}
}
//HANDE USER PREFERENCES FOR GREETING AND ROLE
selectHandler = (e) => {
if (e.target.id === 'greet') {
this.setState({greeting: e.target.value})
} else if (e.target.id === 'role') {
this.setState({role: e.target.value})
}
}
render() {
return (
<div className="container-fluid">
<div className="row">
<Form data={this.state} inputChanged={this.inputHandler} selectChanged={this.selectHandler}/>
<div className="col-md-6 table">
<Table tableFor="Admins table"/>
<Table tableFor="Moderators table"/>
</div>
</div>
</div>
);
}
}
I am not sure if this is an actual problem but I was just curious what might be the reason for that behavior?

As per some of your comments i understand that the real issue you are facing is the the DOM value attribute is not in sync with the value property.
This is by design, there is a lot of talk about this issue and it mostly related to the confusion people do with:
jsx value attribute / property
DOM (devtools html) value attribute
These are not the same thing.
There is another thing to consider, related to passwords exploit.
You can read this issue for better understanding and more details.

Simplify how the inputs are setting state based upon the input's e.target.name and e.target.value. By design, the DOM number input value will only update when unfocused, but state is always up-to-date.
Here's a working example: https://codesandbox.io/s/qzl5knl4kj
formInputs.js
import React, { Fragment } from "react";
export default ({ age, handleChange, name }) => (
<Fragment>
<label>Please, enter your name: </label>
<br />
<input
onChange={handleChange}
type="text"
className="uk-input"
name="name"
placeholder="Name"
value={name}
style={{ width: 300, marginBottom: 10 }}
/>
<br />
<label>How old are you?</label>
<br />
<input
onChange={handleChange}
type="number"
className="uk-input"
name="age"
placeholder="Age"
value={age}
style={{ width: 300, marginBottom: 10 }}
/>
<br />
</Fragment>
);
index.js
import React, { Component } from "react";
import { render } from "react-dom";
import FormInputs from "./formInputs";
import "uikit/dist/css/uikit.min.css";
import "./styles.css";
class App extends Component {
state = {
name: "",
age: "",
greeting: "hello",
role: "admin"
};
handleChange = ({ target: { name, value } }) => this.setState({ [name]: value });
handleFormClear = () => this.setState({ age: "", name: "" });
handleSubmit = e => {
e.preventDefault();
const { age, name } = this.state;
if (!age || !name) return;
alert(`Name: ${name}, Age: ${age}`);
};
render = () => (
<form onSubmit={this.handleSubmit} style={{ textAlign: "center" }}>
<h1>Mixed Input Fields</h1>
<FormInputs {...this.state} handleChange={this.handleChange} />
<button
style={{ marginBottom: 20, marginRight: 10 }}
type="submit"
className="uk-button uk-button-primary"
>
Submit
</button>
<button
style={{ marginBottom: 20 }}
type="button"
className="uk-button uk-button-danger"
onClick={this.handleFormClear}
disabled={!this.state.name && !this.state.age}
>
Clear
</button>
<div>
<pre style={{ margin: "auto", width: 300 }}>
<code>
Name: {this.state.name}
<br />
Age: {this.state.age}
</code>
</pre>
</div>
</form>
);
}
render(<App />, document.getElementById("root"));

Related

multiinput from submission in react js

I am trying to submit a form in react js I have multiple files
this.state = {
allValues: [],
};
changeHandler = (e) => {
this.setState({ ...this.allValues, [e.target.name]: e.target.value });
};
onsubmbit = (e) => {
e.preventDefault();
console.log(this.state.allValues);
};
<form onSubmit={this.onsubmbit}>
<input type='text' name='bloodsugar' onChange={this.changeHandler} value='' />
<input
type='text'
name='bloodpressure'
onChange={this.changeHandler}
value=''
/>
<button type='submit' style={styles.subbtn}>
Submit
</button>
</form>;
I am trying to submit a form in react js I have multiple files
I am trying to submit this form
console.log(this.state.allValues); when i console log it in submit function i want data as
{
bloodsugar:data of bloodsugar,
bloodpressure:data of bloodsugar,
}
when I console log it in submit function I want data like this
You have to set the value of each input field from the state that you set with changeHandler method. Additionally, you need to update the changeHandler method to update the state.allValues as follows.
(Following is the example code I used to test locally. Do the necessary modifications to fit it to your implementation)
import React, { Component } from "react";
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
allValues: {
bloodsugar: "",
bloodpressure: "",
},
};
}
changeHandler = (e) => {
this.setState({
allValues: { ...this.state.allValues, [e.target.name]: e.target.value },
});
};
onsubmbit = (e) => {
e.preventDefault();
console.log(this.state.allValues);
};
render() {
return (
<form onSubmit={this.onsubmbit}>
<div>
<div style={{ fontSize: "4rem", padding: "15px" }}>
<i className="fa fa-level-up"></i>
</div>
<div style={{ padding: "10px" }}>
<strong>Enter your blood sugar level</strong>
<br />
<input
type="text"
name="bloodsugar"
onChange={this.changeHandler}
value={this.state.allValues.bloodsugar}
/>
</div>
</div>
<div>
<div style={{ fontSize: "4rem", padding: "15px" }}>
<i className="fa fa-area-chart"></i>
</div>
<div style={{ padding: "10px" }}>
<strong>Enter your blood pressure level</strong>
<br />
<input
type="text"
name="bloodpressure"
onChange={this.changeHandler}
value={this.state.allValues.bloodpressure}
/>
</div>
</div>
<button type="submit">Submit</button>
</form>
);
}
}

pass formik.values to another js file

I learn react and I am trying to create a stepper to manage my form correct,I'm looking for the best fit way to pass input value from one step to another
The full code is bellow
here the input value from step 1 :
<MDBInput
label="exerciseManager"
name="exerciseManager"
type="text"
value={formik.values.exerciseManager}
onChange={formik.handleChange}
outline
size="lg"
/>
I want to pass formik.values.exerciseManager to step 2 so i can use it there
step 1 and step 2 in different js file
how should I do that correct?
this is step 1 :
I want it will show here :
full step 1 code
//now check that the value get correct to the database
const Certifications = (props) => {
//state //Setstate
const [fieldApproveOptions, setFieldApproveOptions] = useState([])
//useEffect Hooks
useEffect(() => {
axios.get('/api/certifications/fieldApproveOptions?userId=1234567&rank=Colonel&force=Moran')
.then(response => {
console.log(response.data)
setFieldApproveOptions(response.data.fieldApproveOptions)
}
).catch(err => console.log(err))
}, [])
const formik = useFormik({
initialValues: {
exerciseName: '',
//exerciseBy: '', autofill current user from session
exerciseOOB: '',
exercisePOD: '',
exerciseType: '', // options should be pull from db
exerciseLive: '',
fieldApprove: '', // options should be pull from db
fileApprove: '', // options should be pull from db
artilleryApprove: '', // options should be pull from db
exerciseManager: '',
trainerOfficerApprove: '', // options should be pull from db
cerRes: '',
fieldApproveOptions: []
},
onSubmit: values => {
axios.post('/api/certifications', values)
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
},
})
return (
<Card>
<CardContent>
<div className="Pedding">
<MDBContainer fluid >
<MDBRow center >
<MDBCol md="4" >
<div className="MDBColor">
<form onSubmit={formik.handleSubmit} autoComplete="off">
<p className="h1 text-center" style={{ paddingTop: "10px", fontWeight: "bold" }}>Certifications</p>
<div className="Certifications">
<MDBInput
label="Exercise name"
name="exerciseName"
type="text"
onChange={formik.handleChange}
value={formik.values.exerciseName}
outline
size="lg"
/>
<MDBInput
label="Exercise type"
name="exerciseType"
list="types"
onChange={formik.handleChange}
value={formik.values.exerciseType}
outline
size="lg"
/>
<datalist id="types" >
<option data-value="1" value="Open Terrain">Open Terrain</option>
<option value="Urban warfare" >Urban warfare</option>
<option value="Armoured fighting vehicle" >Armoured fighting vehicle</option>
<option value="unplanned" >unplanned</option>
<option value="live military exercise" >live military exercise</option>
</datalist>
<MDBInput
label="Order of battle"
name="exerciseOOB"
type="number"
min="20"
onChange={formik.handleChange}
value={formik.values.exerciseOOB}
outline
size="lg"
/>
{/*FieldApprove button */}
<MDBInput
label="fieldApprove"
name="fieldApprove"
list="fieldApproves"
onChange={formik.handleChange}
value={formik.values.fieldApprove}
outline
size="lg"
/>
<datalist id="fieldApproves" defaultValue>
{fieldApproveOptions.map((option, i) =>
<option key={i++} value={option.id}>
{option.rank + " " + option.firstName + " " + option.lastName}
</option>)}
</datalist>
<MDBInput
label="fileApprove"
name="fileApprove"
type="text"
value={formik.values.fileApprove}
onChange={formik.handleChange}
outline
size="lg"
/>
<MDBInput
label="artilleryApprove"
name="artilleryApprove"
type="text"
value={formik.values.artilleryApprove}
onChange={formik.handleChange}
outline
size="lg"
/>
<MDBInput
label="exerciseManager"
name="exerciseManager"
type="text"
value={formik.values.exerciseManager}
onChange={formik.handleChange}
outline
size="lg"
/>
<MDBInput
label="trainerOfficerApprove"
name="trainerOfficerApprove"
type="text"
value={formik.values.trainerOfficerApprove}
onChange={formik.handleChange}
outline
size="lg"
/>
<div style={{ fontSize: "large", fontWeight: "bold" }} className="custom-control custom-checkbox">
<input type="checkbox"
onChange={formik.handleChange}
value={formik.values.exerciseLive}
className="custom-control-input"
name="exerciseLive"
id="live"
value="on"
/>
<label className="custom-control-label" htmlFor="live"> live exercise</label>
</div>
{/*pod section*/}
<span style={{ fontSize: "large", fontWeight: "bold", float: "left" }} >part of the day:</span>
<div className="forms" style={{ fontWeight: "bold" }} onChange={formik.handleChange} value={formik.values.exercisePOD} >
{/*night button*/}
<label htmlFor="rdo1">
<input type="radio" id="rdo1" name="exercisePOD" value="night" />
<span className="rdo"></span>
<span>night</span>
</label>
{/*day button*/}
<label htmlFor="rdo2">
<input type="radio" id="rdo2" name="exercisePOD" value="day" />
<span className="rdo"></span>
<span>day</span>
</label>
</div>
<div className="text-center">
<MDBBtn type="submit" color="yellow">Send</MDBBtn>
</div>
</div >
</form >
</div>
</MDBCol>
</MDBRow>
</MDBContainer >
</div>
</CardContent>
</Card>
);
}
export default Certifications;
here Soform.js full code
const SoForm = () => {
return (
<p >
{formik.values.exerciseManager}
</p>
)
}
export default SoForm;
Here formikStepper code
export default function Home() {
return (
<Card>
<CardContent>
<FormikStepper
initialValues={{
}}
onSubmit={async (values) => {
await sleep(3000);
console.log('values', values);
}}
>
<FormikStep label="Certifications">
<Box paddingBottom={2}>
<Certifications ></Certifications>
</Box>
</FormikStep>
<FormikStep
label="loginPageF"
>
<Box paddingBottom={2}>
<SoForm ></SoForm>
It's really hard to read and understands your code. Try to provide minimal reproducible statements. I can understand you problem, but can't work with your code. So I have created my won example. Here, codesandbox.io : https://codesandbox.io/s/elegant-shtern-362ki?file=/src/App.js
Let me explain it for you.
index.js -> is entry point, that calls only one component App, as we have no route
App.js -> is the parent component, which has two child, Certification and Panel
Certification.js -> takes input
Panel -> renders data from certification
If I'm not wrong, that's what you want. Render data in a component to another component, which are siblings to one another.
App.js :
import React from "react";
import Certifications from "./Certifications";
import Panel from "./Panel";
class App extends React.Component {
state = {
value1: "",
value2: ""
};
fromCert = (name, value) => {
this.setState({ [name]: value });
};
render() {
return (
<div>
{this.state.value1}
{this.state.value2}
<Certifications fromCert={this.fromCert} />
<Panel value1={this.state.value1} value2={this.state.value2} />
</div>
);
}
}
export default App;
Panel.js:
import React from "react";
class Panel extends React.Component {
render() {
return (
<div>
Here we will render data from App, below
<div>{this.props.value1}</div>
<div>{this.props.value2}</div>
Panel ends
</div>
);
}
}
export default Panel;
Certification.js:
import React from "react";
class Certifications extends React.Component {
state = {
input1: "",
input2: ""
};
onChange = (e) => {
this.setState({ [e.target.name]: e.target.value });
this.props.fromCert(e.target.name, e.target.value);
};
render() {
return (
<div>
<input name="value1" onChange={this.onChange} />
<input name="value2" onChange={this.onChange} />
<div>
Inside certificate
<div>{this.state.input1}</div>
<div>{this.state.input2}</div>
Certificate ends
</div>
</div>
);
}
}
export default Certifications;
First of all, Certifications have two states - value1, value2. So I have given two input's name value1, value2. So that I can set value dynamically. Why? - just imagine I have 10 or 20 states. And that you have in your code.
And onChange of value, I'm triggering a callback to App with fromCert. Try passing 1000+ parameter, it will. :wink:
When I'm triggering that callback from certification, it's getting called in App.js's fromCert. Why is that? Cause I have passed that function or method as parameter - <Certifications fromCert={this.fromCert} />. So that's the reason why this function or method acts as callback. When I get those values, I just set them to App.js's state. Then pass them as props to Panel.
So whatever changes gets applied to Certification that comes to App, which then gets passed to Panel.
Certification -> App : Child to Parent communication
App -> Panel : Parent to Child communication
Certification -> Panel : Child to Child communication / Sibling communication
Try to imagine the hierarchy.
Thanks a lot. If you have any question, feel free to ask.

React state hooks and useEffect unexpected behavior for state updates

So I have a project I did before in Vue and now am doing in React(w/ hooks) in order to learn it. I'm having a few problems and concerns that I'm not going about it the right way(certain I'm not).
One of the biggest problems I'm having is where the state is updated via onchange and onblur. Many times the state values would be one "tick" behind. I found that with old class components you could use a callback within setState.
I'm trying to make instant form validation feedback show/hide as the user updates the fields.
With hooks, it is supposed to be done with useEffect. I have it "working" right now but it seems it's rendering more times than it should. I can tell by the fact it runs the checkValues() twice to show the current state values .
An example of the nature of my misunderstanding is if I don't put setinValid(validateForm()); within the onchange AND the useEffect.. it won't update the state for inValid which disables/enables the submit button. This seems redundant to me and I'm not sure why it "works" as is.
Any help/insight on how to properly do what I'm attempting would be greatly appreciated.
https://codesandbox.io/s/user-listing-in-react-9ip4t?fontsize=14&module=%2Fsrc%2Fcomponents%2FUser%2FUserAdd.js
import React from "react";
import { Link } from "react-router-dom";
// import { saveUserToLocalStorage } from "../../utils/StorageHelper";
// import { User } from "../../utils/UserClass";
const UserAdd = props => {
const [userName, setuserName] = React.useState("");
const [userAge, setuserAge] = React.useState("");
const [userEmail, setuserEmail] = React.useState("");
const [inValid, setinValid] = React.useState(true);
const [errors, setErrors] = React.useState({
name: [],
age: [],
email: []
});
React.useEffect(() => {
checkValues();
setinValid(validateForm());
}, [userName, userAge, userEmail, inValid]);
const validateForm = () => {
if (isNaN(userAge)) {
return true;
}
if (!userName || !userAge || !userEmail) {
return true;
}
if (!validateEmail(userEmail)) {
return true;
}
return false;
};
function checkIndividualErrors() {
if (userName.length === 0) {
setErrors({ ...errors, name: ["User name is required"] });
} else {
setErrors({ ...errors, name: [] });
}
}
const checkValues = () => {
console.log(
"username:",
userName,
"age:",
userAge,
"useremail: ",
userEmail,
"invalid:",
inValid
);
};
const validateEmail = mail => {
if (/^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(mail)) {
return true;
}
return false;
};
return (
<div>
<h2 class="line-container">
<span>Add a new User</span>
</h2>
<hr />
<div class="field is-horizontal">
<div class="field-label is-normal">
<label class="label">Name</label>
</div>
<div class="field-body">
<div class="field">
<p class="control">
<input
class="input"
type="text"
name="name"
placeholder="Name"
value={userName}
onChange={e => {
setuserName(e.target.value);
setinValid(validateForm());
checkIndividualErrors();
}}
onBlur={checkIndividualErrors}
/>
<span class="error">{errors.name}</span>
</p>
</div>
</div>
</div>
<div class="field is-horizontal">
<div class="field-label is-normal">
<label class="label">Age</label>
</div>
<div class="field-body">
<div class="field">
<p class="control">
<input
class="input"
type="text"
name="age"
placeholder="Age"
value={userAge}
onChange={e => {
setuserAge(e.target.value);
setinValid(validateForm());
// checkIndividualErrors not fully implemented yet
}}
/>
<span class="error" />
</p>
</div>
</div>
</div>
<div class="field is-horizontal">
<div class="field-label is-normal">
<label class="label">Email</label>
</div>
<div class="field-body">
<div class="field">
<p class="control">
<input
class="input"
type="email"
name="email"
placeholder="Email"
value={userEmail}
onChange={e => {
setuserEmail(e.target.value);
setinValid(validateForm());
// checkIndividualErrors not fully implemented yet
}}
/>
<span class="error" />
</p>
</div>
</div>
</div>
<p class="" style={{ margin: "0 auto" }}>
<button
disabled={inValid}
class="button is-primary"
style={{ marginRight: "10px" }}
>
Create
</button>
<Link to="/" class="button">
Cancel
</Link>
<Link to="/" class="goBack">
<span style={{ fontSize: "20px" }}>←</span>
</Link>
</p>
</div>
);
};
export default UserAdd;

How do I define functions in parent component and pass them to respective child components?

More of a two part question: I need to define each of the onChange handle functions in my parent component and pass them to respective child components. After that How would I get the value of form elements in your parent component?
class App extends Component {
render() {
const handleChange = (data) =>
{console.log(data)}
return (
<div className="App">
<PageOne handleChange={handleChange} />
<PageTwo />
<PageThree />
<PageFour />
<PageFive />
<PageSix />
<Button onSubmit={this.props.handleChange()}>
Submit Form
</Button>
<br/>
<br/>
</div>
);
}
}
Page One Component
class PageOne extends Component {
constructor(props){
super(props)
this.state={
generalDetails: '',
phoneNumber: '',
fName: '',
mName: '',
lName: '',
gender: '',
}
this.handleInputChange = this.handleInputChange.bind(this);
}
handleChange = (data) =>
{console.log(data)
}
handleInputChange(event) {
const target = event.target;
const value = target.type === 'checkbox' ? target.checked :
target.value;
const name = target.name;
console.log(`Input name ${name}. Input value ${value}.`);
this.setState({
[name]: value
});
}
render() {
return (
<div className="PageOneWrapper"
style={{
background: '#969fad'
}}
>
<div className="Details">
<h1>CareerTrackers Program Orientation</h1>
<p> Please complete this form to ensure we have your most up-to-date contact details. </p>
<Form>
<TextArea
onChange={this.handleInputChange}
name="generalDetails"
placeholder='General Details'
style={{
width: 500,
minHeight: 50
}}
/>
</Form>
<br/>
<p style={{
marginRight: 600
<Input
onChange={this.handleInputChange}
name='fName'
placeholder='First Name'
/>
<Input
onChange={this.handleInputChange}
name='mName'
placeholder='Middle Name'
style={{
marginLeft: 50,
marginRight: 50
}}
/>
<Input
onChange={this.handleInputChange}
name='lName'
placeholder='Last Name'
/>
<br/><br/><br/>
<p
style={{
display: "inline",
marginRight: 480
}}
><strong>Gender: </strong>
</p>
<select
name='gender'
onChange={this.handleInputChange}
style={{
display: "inline",
}}
>
<option>Select Gender </option>
<option>Male </option>
<option>Female </option>
<option>Other </option>
</select>
<br/><br/><br/>
<p style={{
marginRight: 600
}}><strong>Email:</strong></p>
<Input
onChange={this.handleInputChange}
name='email'
placeholder='Email'
style={{
marginRight: 470,
}}
/>
<br/>
<br/>
<Input
onChange={this.handleInputChange}
name='confirmEmail'
placeholder='Confirm Email'
style={{
marginRight: 470,
}}
/>
<br/>
<br/>
<p style={{
marginRight: 540
}}><strong>Phone Number:</strong></p>
<Input
onChange={this.handleInputChange}
name='phoneNumber'
placeholder='Phone Number'
style={{
marginRight:370,
}}
/>
<select
onChange={this.handleInputChange}
name='Mobile Type'
style={{
MarginRight: 5000
}}
>
<option>Mobile Type</option>
<option>Mobile</option>
<option>Work</option>
<option>Home</option>
</select>
<br/>
<br/>
<br/><br/><br/>
</div>
</div>
);
}
}
export default PageOne;
I've summarized what you want.
There are several pages for user inputs
These pages are child of parent
Submit button and submit function is defined in parent
You want to put all input data in many pages into the submit function
How can I do this?
If above is correct, and you've not considered about React-Redux,
I highly recommend to try it.
React Redux is the official React binding for Redux. It lets your React components read data from a Redux store, and dispatch actions to the store to update data.
It would help to handle your situation.
By using it, you can store your various data into Redux store - it is central data storage
Eg. you can save many inputs into Redux store in child component, and read values from Redux store in parent component.
Here is sample code that will help you:
APP.js
import React, { Component } from 'react';
import './App.css';
import PageOne from './PageOne';
class App extends Component {
constructor(props){
super(props)
this.state={
generalDetails: 'Initial Text',
}
this.onContentChange = this.onContentChange.bind(this);
this.onSubmitForm = this.onSubmitForm.bind(this);
}
render() {
return (
<div>
<h1>{this.state.generalDetails}</h1>
<PageOne handleChange={this.onContentChange} />
<button onSubmit={this.onSubmitForm}>
Submit Form
</button>
</div>
);
}
onSubmitForm(){
//Perform all Required Logic on Form Submit
}
onContentChange(data){
console.log('in onContentChange');
console.log(data);
this.setState({
...this.state,
generalDetails: data.generalDetails
});
console.log(this.state);
}
}
export default App;
PageOne.js
import React, { Component } from 'react';
class PageOne extends Component {
constructor(props){
super(props)
this.state={
generalDetails: ''
}
this.handleInputChange = this.handleInputChange.bind(this);
}
handleInputChange(event) {
const target = event.target;
const value = target.type === 'checkbox' ? target.checked :
target.value;
const name = target.name;
console.log(`Input name ${name}. Input value ${value}.`);
this.setState({
...this.state,
[name]: value
});
if(this.props.handleChange){
this.props.handleChange(this.state);
}
}
render() {
return <div>
<textarea
onChange={this.handleInputChange}
name="generalDetails"
placeholder='General Details'
style={{
width: 500,
minHeight: 50
}}
/>
</div>
}
}
export default PageOne;
I have added only one field as this is just sample code. You can updated code based on your requirements.

Form validation visible in React after entering correct values

I have a basic login form, I have implemented the form validation using material UI.
The validation is visible even when there is a value in the text box.
code:
LoginComponent
import React from "react";
import TextField from "material-ui/TextField";
import RaisedButton from "material-ui/RaisedButton";
export class loginComponent extends React.Component {
constructor() {
super();
this.state = {
username: "",
usernameError: "",
password: "",
passwordError:""
};
};
onChange = e => {
this.setState({
[e.target.name]: e.target.value
});
};
validate = () => {
let isError = false;
const errors = {
usernameError: "",
passwordError: ""
};
if (this.state.username.trim.length === 0) {
isError = true;
errors.usernameError = "Username is required";
}
if (this.state.password.trim.length === 0) {
isError = true;
errors.passwordError = "password is required";
}
this.setState({
...this.state,
...errors
});
return isError;
}
onSubmit = e => {
e.preventDefault();
const error = this.validate();
if (!error) {
console.log(this.state);
}
};
render() {
return (
<div className="container">
<div id="loginbox" style={{ marginTop: 50 }} className="mainbox col-md-6 col-md-offset-3 col-sm-8 col-sm-offset-2">
<div className="panel panel-info">
<div className="panel-heading">
<div className="panel-title">Sign In</div>
</div>
<div style={{ paddingTop: 30 }} className="panel-body">
<form id="loginform" className="form-horizontal" role="form">
<div style={{ marginBottom: 25 }} className="input-group">
<span className="input-group-addon"><i className="glyphicon glyphicon-user"></i></span>
<TextField
name="username"
floatingLabelText="User name"
value={this.state.username}
onChange={e => this.onChange(e)}
errorText={this.state.usernameError}
floatingLabelFixed
/>
</div>
<div style={{ marginBottom: 25 }} className="input-group">
<span className="input-group-addon"><i className="glyphicon glyphicon-lock"></i></span>
<TextField type="password"
name="password"
value={this.state.password}
floatingLabelText="password"
onChange={e => this.onChange(e)}
errorText={this.state.passwordError}
floatingLabelFixed
/>
</div>
<div style={{ paddingTop: 10 }} className="form-group">
<div className="col-sm-12 controls">
<RaisedButton label="Login" onClick={e => this.onSubmit(e)} primary />
</div>
</div>
</form>
</div>
</div>
</div>
</div>
);
}
}
This are basic required length validation that is still getting fired even after entering the values in text box, can someone suggest what i did wrong.
I think with your comparison:
this.state.password.trim.length will always return 0 as it calculating length of password.trim.
Use this.state.password.trim().length which will trim passowrd value and return its length.

Resources