I've created very simple form for user to sign in. Here is my code:
import React,{ Component } from 'react';
class SignIn extends Component {
constructor(props) {
super(props);
this.state = {
login:"",
pass:""
}
}
signIn = (e) =>{
e.preventDefault();
alert("in")
}
handleChange = (propertyName) => (e) => {
const state = this.state;
const newState = {
...state,
[propertyName]: e.target.value
};
this.setState(newState);
}
render() {
return (
<div className="text-center">
<form onSubmit={this.signIn}>
<input type="text" id="login" onChange={this.handleChange('login')} value={this.state.login} placeholder="login"/>
<br />
<input type="password" id="pass" onChange={this.handleChange('pass')} value={this.state.pass} placeholder="pass"/>
<br />
<input type="submit" value="sign in" disabled={((this.state.login == "") && (this.state.pass == ""))
? true
: false}/>
</form>
</div>
);
}
}
export default SignIn;
For some reason every time I start my app these inputs already have some text inside. "login" always have "localhost" and "pass" contains some random numbers and letters. Can someone explain me where are these values comming from?
These fields are auto-populated by browser. See explanation here: https://developers.google.com/web/updates/2015/06/checkout-faster-with-autofill
Also you might be interested in this question of how people fighting with it :)
Chrome Browser Ignoring AutoComplete=Off
Related
I have some basic knowledge in programming and web-development.
I'm just trying something on Reactjs and already tried to read some documentation. I want to keep the code as simple as possible.
What I'm trying is just a validation if the text in the input field is "xyz" but somehow the validation is always wrong. Sometimes the if statement is true even with the wrong input.
What am I missing and how can I do it better?
import React from 'react';
class LoginForm extends React.Component {
constructor(props){
super(props);
this.state = {username:'' , password:''};
}
Submit = (event)=> {
event.preventDefault();
let user=this.state.username;
if(user == "xyz"){
alert("This works!");
} else{
alert("not working :/");}
}
render() {
return (
<form className="LoginForm" onSubmit={this.Submit}>
<p> Enter here</p>
<input type="text"/>
<input type="submit"/>
</form>
)
}}export default LoginForm
You currently are not capturing the onChange of the input. You must create an onChange event handler like so:
import React from "react";
class LoginForm extends React.Component {
constructor(props) {
super(props);
this.state = { username: "", password: "" };
}
formValidation = () => {
let errors = {};
if (!this.state.username) {
errors.username = "username must not be empty";
}
if (!this.state.password) {
errors.password = "password Must not be empty";
}
return errors;
};
handleInputChange = (field) => (e) =>
this.setState({ [field]: e.target.value });
Submit = (event) => {
event.preventDefault();
let errors = this.formValidation();
if (errors.username) {
alert(errors.username);
}
if (errors.password) {
alert(errors.password);
}
if (!errors.username && !errors.password) {
alert("success");
}
};
render() {
console.log(this.state.username);
return (
<form className="LoginForm" onSubmit={this.Submit}>
<p> Enter here</p>
<input
onChange={this.handleInputChange("username")}
value={this.state.username}
type="text"
placeholder="username"
/>
<input
onChange={this.handleInputChange("password")}
value={this.state.password}
type="text"
placeholder="password"
/>
<input type="submit" />
</form>
);
}
}
export default LoginForm;
I also created a formValidation function that returns an error object which to me is a bit cleaner.
Here is a code pen to see the code in action: https://codesandbox.io/s/determined-morning-rpzd2?file=/src/App.js
EDIT: I have updated the answer for a use case involving both inputs.
This is a simplified scenario.
I have a form with a required input field and a button. The button has an onClick React handler and is of type "button". I want the browser to check the HTML fields and do some initial validation (like it would do if no React were involved and the button were of type "submit"). I imagine I should do something in the handler function, but I am not sure what.
A few things I tried:
Changing the button to type "submit" does perform the check, but also calls the handler, which does not know whether the check succeeded or failed
Adding the handler on the form instead works, but makes the real example harder to maintain because I have a lot of buttons
Thank you
<div id="app"></div>
class MyClass extends React.PureComponent {
render() {
return (
<form action="#">
<input type="text" required/>
<button type="button" onClick={e => this.handle(e)}>Press</button>
</form>
)
}
handle(event) {
// What should I do here?
}
}
ReactDOM.render(<MyClass />, document.querySelector("#app"))
https://jsfiddle.net/89wr3ot4/
It looks like form has a checkValidity() and reportValidity() API. The answer then becomes
class MyClass extends React.PureComponent {
render() {
return (
<form action="#" ref={this.formRef}>
<input type="text" required/>
<button type="button" onClick={e => this.handle(e)}>Press</button>
</form>
)
}
handle(event) {
const form = this.formRef.current;
if (!form.checkValidity()) {
form.reportValidity()
return
}
// Everything else
}
}
ReactDOM.render(<MyClass />, document.querySelector("#app"))
You need to create state for input value
const [inputValue, setInputValue] = useState(''); //for functional component
const inputHandler = (event) => setInputValue(event.target.value);
then
<input type='text' value={inputValue} onChange={inputHandler} />
and check in your 'handler' function what you want.
handle(event) {
if (inputValue.length > 0) //do what you want...
}
Following is working example which is modified from above jsfiddle
class MyClass extends React.Component {
state = { value: '', message: ''}
render() {
return (
<form action="#">
<input type="text" required value={this.state.value} onChange={e => this.setState({value: e.target.value})} />
<button type="button" onClick={e => this.handle(e)}>Press</button>
<p> {this.state.message }</p>
</form>
)
}
handle(event) {
// What should I do here?
const { value } = this.state;
if (value === '') {
this.setState({message: 'Invalid!, Please enter valid input'})
} else {
this.setState({message: 'Yeah!, Got Valid input'})
}
}
}
ReactDOM.render(<MyClass />, document.querySelector("#app"))
Here I provide my code where I want to enter characters into the password input field and I want to do not enter whitespace/space in it but it also going inside of it instead when I print input value then it does not contain space/whitespace. Please help me to resolve the issue.
CodeSandBox Demo
Code -
import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";
import { Form, Input, Label } from "semantic-ui-react";
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
inputFieldData: {
pass: {
val: "",
error: false
}
}
};
}
inputChange = e => {
// prevent not to enter space charactes in password field while registering
const re = /^\S*$/;
let inputFieldData = this.state.inputFieldData;
const name = e.target.name;
if (re.test(e.target.value)) {
inputFieldData[name]["val"] = e.target.value;
console.log(e.target.value);
}
this.setState({ inputFieldData });
};
render() {
const { inputFieldData } = this.state;
return (
<div className="App">
<h1>Input box does not contain space in it</h1>
<h3>Input Value: {inputFieldData["pass"]["val"]}</h3>
<Form className="register-form">
<Form.Field>
<Input
type="password"
icon="user circle"
name="pass"
iconPosition="left"
placeholder="Enter Password"
onChange={this.inputChange}
error={inputFieldData["pass"]["error"]}
/>
{inputFieldData["pass"]["error"] && (
<Label basic color="red" pointing>
Field can not be empty
</Label>
)}
</Form.Field>
</Form>
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
You need to use the controlled component pattern (see here https://reactjs.org/docs/forms.html#controlled-components) by adding the value prop to your input component.
You can then add the space trimming logic in your handleChange function.
Here is an example : https://codesandbox.io/s/kkpr53k36r
You need to set the value of the input to inputFieldData.pass.val,
otherwise it is not bound to the state of your component.
<Input
value={inputFieldData.pass.val}
type="password"
icon="user circle"
name="pass"
iconPosition="left"
placeholder="Enter Password"
onChange={this.inputChange}
error={inputFieldData["pass"]["error"]}
/>
I solved this problem with regex
str.replace(/\s/g, '')
Simply do like this in handleOnChange Function:
handleOnChange = (e) => {
this.setState({
[e.target.name]: e.target.value.split(" ").join("")
});
};
I am creating a simple client-side login form. When a user logs in the state currentAdmin changes to true (it's false by default). By some reason, setState throws a Warning A component is changing an uncontrolled input of type submit to be controlled. Input elements should not switch from uncontrolled to controlled (or vice versa). Decide between using a controlled or uncontrolled input element for the lifetime of the component.
I tried using refs in Header.js but this didn't help.
App.js
import React, { Component } from 'react';
import Header from '../Header/Header';
class App extends Component {
constructor(props) {
super(props)
this.state = {
currentAdmin: false
}
}
onSignIn = (login, password) => {
if (login === 'admin' && password === '123') {
this.setState({
currentAdmin: true
})
}
}
onSignout = () => {
this.setState({
currentAdmin: false,
})
}
render() {
return (
<div>
<Header
onSignin={this.onSignIn.bind(this)}
onSignout={this.onSignout.bind(this)}
currentAdmin={this.state.currentAdmin}
/>
</div>
)
}
}
export default App.js;
Header.js
import React, {Component} from 'react';
import './Header.css';
class Header extends Component {
constructor(props) {
super(props);
this.handleSignin = this.handleSignin.bind(this);
this.handleSignout = this.handleSignout.bind(this);
}
handleSignin(e) {
e.preventDefault();
let login = this.refs.login.value;
let password = this.refs.password.value;
this.props.onSignin(login, password);
}
handleSignout(e) {
e.preventDefault();
this.props.onSignout();
}
render() {
if (this.props.currentAdmin === false) {
return (
<div className='header'>
<a href='google.com' className='logo'>ToDoApp</a>
<form className='login' onSubmit={this.handleSignin}>
<input type='text' placeholder='login' ref='login'/>
<input type='password' placeholder='password' ref='password'/>
<input type='submit' value='Log in'/>
</form>
</div>
);
} else {
return (
<div className='header'>
<a href='google.com' className='logo'>ToDoApp</a>
<form className='login' onSubmit={this.handleSignout}>
<input type='submit' value='Log out'/>
</form>
</div>
);
}
}
}
export default Header;
This throws a Warning.
You need to use defaultValue property on input instead of value. Check docs here.
As other option - you may want to replace input type="submit" with button type="submit"
ALexand Tovmach provided perfect (personally for me) answer. I should have changed <input type='submit' value='Log in/>to <button type='submit'>Log in</button>
I have the following code which is intended to get the input fed to ToggleForm component (which is a form) and store it in employeeData state. However, the problem is that whenever I press the submit button of ToggleForm for the first time after execution, "" value gets stored first in the employeeData state and it is only after I click the submit button for the second time that the data fed in the form comes to employeeData.
This must be a minor mistake. But I am not being able to figure it out.
import React from "react";
import ToggleForm from "./ToggleForm";
let employee = "";
class Home extends React.Component {
constructor(){
super();
this.state = {
employeeData: ""
};
}
addEmployee(e) {
e.preventDefault();
let name = e.target.name.value;
let address = e.target.address.value;
let salary = e.target.salary.value;
this.setState({
employeeData: [...this.state.employeeData, { name, address, salary }]
});
employee = [...this.state.employeeData];
console.log(employee);
}
render() {
return (
<div className="container">
<ToggleForm addEmployee={this.addEmployee.bind(this)}/>
</div>
);
}
}
export default Home;
Here is the ToggleForm component:
import React from 'react';
class ToggleForm extends React.Component {
render(){
return(<div>
<br/>
<h3>Add a new employee</h3>
<hr/>
<form className="form-group" onSubmit = {this.props.addEmployee}>
<input className="form-control" type="text" name="name" placeholder="Name of the employee"/><br/>
<input className="form-control" type="text" name="address" placeholder="Address of the employee"/><br/>
<input className="form-control" type="text" name="salary" placeholder="Salary of the employee"/><br/>
<input type="submit" className="btn btn-primary"/>
</form>
</div>)
}
}
export default ToggleForm;
setState is async and fortunately accepts an optional callback. Using the callback, you can access the most current value of state.
this.setState({
employeeData: [...this.state.employeeData, { name, address, salary }]
}, () => {
employee = [...this.state.employeeData];
});
Because setState is async so your need to setState in the component Toggle form when the text is change before ship it the parent component.
For example:
<input
onChange={this.handleChange}
className="form-control"
type="text"
name="name"
value={this.state.name}
placeholder="Name of the employee"
/>
<br />
Function handleChange:
handleChange = (e) => {
this.setState({ [e.target.name]: e.target.value });
console.log(e.target.value)
};
And then ship it to the parent:
handleSubmit = e => {
e.preventDefault();
const { name, address, salary } = this.state;
this.props.addEmployee({ name, address, salary });
};
Check my code here: https://codesandbox.io/s/ww5331jrxl
There are few basic correction in your components:
User super(); in the constructor before this.setState();
If you are not using this.state.employeeData, then don't set it in the state.
If you set the state then you will get the employeeData in the callback function as described by #Andy or you can use the following:
employee = [...this.state.employeeData, { name, address, salary }]