My form does not accept the input value from a user - reactjs

I have a login form i created with react-strap I am facing a problem with input value, the form behave as readonly for the first input of email but accept the second input of the password.
I have tried to delete the email field to trace if the password field will fail to accept input but it worked perfect
I have attached my component code, Please i will appreciate anyone who can help to solve this problem
import React, { Component } from 'react';
import { Button, Card, CardBody, Col, Container, Form, Input, InputGroup, Row } from
'reactstrap';
import './Login.css'
class Login extends Component {
constructor(props) {
super(props)
this.state = {
email:'',
password:''
}
}
changeHandler = (e) =>{
this.setState({[e.target.name]:e.target.value });
}
onSubmit = (e) =>{
e.preventDefault();
fetch('http://localhost:5000/user/login',{
method:'POST',
body:JSON.stringify(this.state),
})
.then(response =>{
if(response.status === 200){
this.props.history.push('/')
}else{
const error = new Error(response.error);
throw error;
}
})
.catch(err=>{
console.error(err);
alert('Ooops! Login failed please check your email and password, then try again')
})
}
render() {
return (
<div className="app flex-row align-items-center">
<Container className="container">
<Row className="justify-content-center">
<Col md="12" lg="10" xl="8">
<Card className="mx-4">
<CardBody className="p-4">
<Form onSubmit={this.onSubmit} className="login-form">
<h1>Login Form</h1>
<InputGroup className="mb-3">
<Input type="email "
name="email "
required="required"
placeholder="email "
value={this.state.email }
onChange={this.changeHandler}
/>
</InputGroup>
<InputGroup className="mb-3">
<Input type="password"
name="password"
required="required"
placeholder="Password"
value={this.state.password}
onChange={this.changeHandler}
/>
</InputGroup>
<Row>
<Col xs="12" sm="6">
<Button type="submit" className="btn btn-info mb-1" block><span>Login</span>
</Button>
Home
</Col>
</Row>
</Form>
</CardBody>
</Card>
</Col>
</Row>
</Container>
</div>
)
}
}
export default Login;

The issue is you have a space in your input name:
<Input type="email "
name="email "
^ remove this space
As a result of that, your change handler fails to set the state because it's setting "email " not "email".
You also have a space in your input type and placeholder.

The problem may be in changeHandler. As you pass it to a input like
onChange={this.changeHandler}
The this in
changeHandler = (e) =>{
this.setState({[e.target.name]:e.target.value });
}
refers to input and not to Class component, so it does not update the state.
To fix this the problem you should bind the Class component this to changeHandler.
constructor(props) {
super(props);
this.state = {
email:'',
password:''
}
this.changeHandler = this.changeHandler.bind(this);
}
You may also read this article.

Related

How do I code a temporary array of email, password pairs and that it could contain made-up emails?

I'm working on a web app using Typescript+React. Since I don't have much knowledge on Redux and database management, I want to code a simple authentication process in which an array would have pre-made email, password pairs. For example, an array of [ {email: jane.doe#gmail.com, password: jane123}, {john.doe#gmail.com, password: joe123}, etc.]. If a user enters something other than the listed email-password pairs, there'd be an alert. Basically, a user is going to enter an email and password on the sign in screen and there will need to be a code to take what they typed in and check it against the known list of email and password (array). How do I go about doing so? (I'm new to TS+React so I have very limited knowledge on this)
I've attached the SigninPage I coded, if it helps.
import React from "react";
import "../../App.css";
import { pages } from '../../App'
import logo from "../../assets/Logo.png"
import Form from 'react-bootstrap/Form'
import FormControl from 'react-bootstrap/FormControl'
import Button from 'react-bootstrap/Button'
interface SigninPageProps {//Contructor like for the page, these two methods are provided by the App for AddItemsPage to use
changePage: (page: pages) => void;
saveSigninInfo: (e: string, p: string) => void;
}
export default class SigninPage extends React.Component<SigninPageProps, any> {
emailRef: React.RefObject<HTMLInputElement>;
passwordRef: React.RefObject<HTMLInputElement>;
constructor(props: any) {
super(props);
this.emailRef = React.createRef();
this.passwordRef = React.createRef();
}
render() {
return (
<div className="main">
<div className="header">
<button>About Us</button>
<button>Contact</button>
</div>
<div className="logo">
<img src={logo} alt="Logo shows up" style={{ width: "400px" }}></img>
<h1>Dismiss Misinformation with More Information!</h1>
</div>
<div className="form">
<Form onSubmit={this.handleSubmit}>
<Form.Group controlId="formBasicEmail">
<Form.Label>Email </Form.Label>
<FormControl
type="email"
placeholder="Email"
ref={this.emailRef} />
</Form.Group>
<Form.Group controlId="formBasicPassword">
<Form.Label>Password </Form.Label>
<Form.Control
type="password"
placeholder="Password"
ref={this.passwordRef} />
</Form.Group>
<Form.Group controlId="formBasicCheckbox">
<Form.Check type="checkbox" label="Check me out" />
</Form.Group>
<Button onClick={(e) => this.props.changePage(pages.HomePage)} variant="primary" type="submit">
Submit
</Button>
</Form>
</div>
</div>
);
}
private handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
if (this.emailRef.current == null || this.passwordRef.current == null) {
alert('INTERNAL ERROR: missing reference!');
return;
}
this.props.saveSigninInfo(this.emailRef.current.value, this.passwordRef.current.value);
this.props.changePage(pages.HomePage)
}
}

React Js Login Beginner

first of all I am a very beginner at React.js. I am creating my super simple static code which has to login the user by the credentials provided in the state and redirect to homepage. But for some reason it doesn't work and doesn't redirect me to the homepage, which has the route of '/', btw my Login route is '/login'. I would appreciate any help. Here is my code:
import React from 'react';
import TextField from '#material-ui/core/TextField';
import { makeStyles } from '#material-ui/core/styles';
import Typography from '#material-ui/core/Typography';
import Container from '#material-ui/core/Container';
import Button from '#material-ui/core/Button';
import HomePage from './HomePage';
import { Redirect } from 'react-router-dom';
class LoginPage extends React.Component {
constructor(props) {
super(props);
this.state = {
loginData: {
username: 'test',
password: 'test'
},
errors: {}
};
this.buttonClickHandle = this.buttonClickHandle.bind(this);
this.loginHandle = this.loginHandle.bind(this);
}
loginHandle(event) {
let field = event.target.name;
let value = event.target.value;
let loginData = this.state.loginData;
loginData[field] = value;
this.setState({loginData: loginData});
}
buttonClickHandle(event) {
event.preventDefault();
if ( this.state.loginData.username === this.target.username) {
console.log("User exists. Go to the login page");
return <Redirect to="/"/>
} else {
console.log("User doesn't exists. Show error message");
}
}
render() {
return (
<div className="loginPage">
<Container maxWidth="sm">
<h2>Login</h2>
<form noValidate autoComplete="off" onChange={this.loginHandle}>
<div className="loginForm">
<TextField
required
id="outlined-required"
label="E-mail"
variant="outlined"
placeholder="Your e-mail..."
className="loginInput"
/>
<TextField
required
id="outlined-password-input"
label="Password"
type="password"
autoComplete="current-password"
variant="outlined"
placeholder="Your password..."
className="loginInput"
/>
<Button
variant="contained"
color="primary"
onClick={this.buttonClickHandle}
>
Login
</Button>
</div>
</form>
</Container>
</div>
)
}
}
export default LoginPage
There are some things that look off in your code.
There is no onChange prop in forms only onSubmit
The button should trigger the onSubmit function, this is done by setting the type of the button as submit
To get the input values from the form you need to put a name and get them as event.target.name.value inside the onSubmit function
here is a working example of your code
class LoginPage extends React.Component {
constructor(props) {
super(props);
this.state = {
loginData: {
username: "test",
password: "test"
},
errors: {}
};
this.handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit(event) {
event.preventDefault();
if (
this.state.loginData.username === event.target.username.value &&
this.state.loginData.password === event.target.password.value
) {
console.log("User exists. Go to the login page");
return <Redirect to="/" />;
} else {
console.log("User doesn't exists. Show error message");
}
}
render() {
return (
<div className="loginPage">
<Container maxWidth="sm">
<h2>Login</h2>
<form noValidate autoComplete="off" onSubmit={this.handleSubmit}>
<div className="loginForm">
<TextField
required
name="username"
id="outlined-required"
label="E-mail"
variant="outlined"
placeholder="Your e-mail..."
className="loginInput"
/>
<TextField
required
name="password"
id="outlined-password-input"
label="Password"
type="password"
autoComplete="current-password"
variant="outlined"
placeholder="Your password..."
className="loginInput"
/>
<Button variant="contained" color="primary" type="submit">
Login
</Button>
</div>
</form>
</Container>
</div>
);
}
}
export default LoginPage;

react-bootstrap - Form.Control defaultValue not updated when re-rendered

When I call setState and my form is re-rendered, the value of the text input doesn't change.
import React, { Component } from 'react';
import { Button, Col, Form, Row } from 'react-bootstrap';
export default class Test extends Component {
constructor(props) {
super(props);
this.state = {
status: "new"
}
}
approve = (e) => {
this.setState({
status: "I'm newer than you!"
});
e.preventDefault();
}
render() {
return (
<div>
Status is {this.state.status}
<Form onSubmit={this.approve}>
<Form.Group as={Row} controlId="status">
<Form.Label column >Status</Form.Label>
<Col>
<Form.Control readOnly type="text" size="sm" defaultValue={this.state.status} />
</Col>
</Form.Group>
<Form.Group as={Row}>
<Button type="submit">approve</Button>
</Form.Group>
</Form>
</div>
);
}
}
When I click on the button, I see the static text ("Status is ...") get updated but the input field does not. Have I wrongly assumed the text input should update?
If you want to change it, you can replace 'defaultValue' with 'value' in FormControl component.
<Form.Control readOnly type="text" size="sm" value={this.state.status} />

Getting Data From React-Bootstrap Input

I am not finding good docs or videos on how to get data from my inputs with React-Bootstrap. I want to be able to click the button and then bring what I typed into the input box into my onClick function.
import React from "react";
import Button from 'react-bootstrap/Button';
import './Search.css';
import InputGroup from 'react-bootstrap/InputGroup';
import FormControl from 'react-bootstrap/FormControl';
class search extends React.Component {
constructor(props){
super(props);
this.text = React.createRef();
this.searchChar = this.searchChar.bind(this);
}
searchChar = () => {
console.log("Button Clicked")
const value = this.input.current.value;
console.log(value)
}
render() {
return (
<div className="searchBar">
<form>
<InputGroup className="mb-3">
<InputGroup.Prepend>
<InputGroup.Text id="basic-addon1">Character Search</InputGroup.Text>
</InputGroup.Prepend>
<FormControl ref = {this.input}
placeholder="Character Name"
aria-label="Character Name"
aria-describedby="basic-addon1"
/>
</InputGroup>
<Button onClick={this.searchChar(this.input)} variant="outline-danger">Search </Button>
</form>
</div>
);
}
}
export default search;
Just try to write your input values in state
for example;
import React from "react";
import Button from 'react-bootstrap/Button';
import './Search.css';
import InputGroup from 'react-bootstrap/InputGroup';
import FormControl from 'react-bootstrap/FormControl';
class search extends React.Component {
constructor(props){
super(props);
this.state = {
basicAddon1 : null,
};
}
searchChar = () => {
console.log("Button Clicked")
const value = this.state.basicAddon1;
console.log(value)
}
render() {
return (
<div className="searchBar">
<form>
<InputGroup className="mb-3">
<InputGroup.Prepend>
<InputGroup.Text id="basic-addon1">Character Search</InputGroup.Text>
</InputGroup.Prepend>
<FormControl
placeholder="Character Name"
aria-label="Character Name"
aria-describedby="basic-addon1"
onChange={event => {
this.setState({
basicAddon1 : event.target.value
});
}}
value={this.state.basicAddon1 ? this.state.basicAddon1 : ""}
/>
</InputGroup>
<Button onClick={this.searchChar(this.input)} variant="outline-danger">Search </Button>
</form>
</div>
);
}
}
export default search;
you can create inputChangeHandler function or something else for improve your code
it just basic
The same way you deal with getting data from a form in pure React, you do with react-bootstrap. This answer here shows many options to do so.
My favourite approach among those options is this one. Using that approach your code would be something like:
class search extends React.Component {
constructor(props) {
super(props)
this.handleSave = this.handleSave.bind(this)
}
onChange(event) {
// Intended to run on the change of every form element
event.preventDefault()
this.setState({
[event.target.name]: event.target.value,
})
}
handleSave() {
console.log(`Do something with : {this.state.characterName}`)
}
render() {
return (
<div className="searchBar">
<form>
<InputGroup className="mb-3">
<InputGroup.Prepend>
<InputGroup.Text id="basic-addon1">
Character Search
</InputGroup.Text>
</InputGroup.Prepend>
<FormControl
name="characterName"
placeholder="Character Name"
aria-label="Character Name"
aria-describedby="basic-addon1"
onChange={this.onChange.bind(this)}
/>
</InputGroup>
<Button onClick={this.handleSave} variant="outline-danger">
Search{' '}
</Button>
</form>
</div>
)
}
}

TypeError: Cannot convert undefined or null to object React Validation

I have used React validation library
https://www.npmjs.com/package/react-validation
If I visit my page from any other page, it does not give any error. but when I refresh the page, it gives an error
TypeError: Cannot convert undefined or null to object
Please suggest an idea if anybody has faced this issue before.
Code:
import React from 'react';
import {
Card,
CardBody,
CardTitle,
Row,
Col,
FormGroup,
Label,
Alert
} from 'reactstrap';
import Input from 'react-validation/build/input';
import Button from 'react-validation/build/button';
import Form from 'react-validation/build/form';
import axios from 'axios';
import api from '../../config/api';
import messages from '../../config/messages';
import Select from 'react-validation/build/select';
import CKEditor from '#ckeditor/ckeditor5-react';
import ClassicEditor from '#ckeditor/ckeditor5-build-classic';
const required = (value, props,components) => {
if(components.formReset!=undefined)
{
if (!components.formReset[0].value && (!value || (props.isCheckable && !props.checked))) {
return <span className="text-danger is-visible">{messages.required}</span>;
}
else if(components.formReset[0].value)
{
return <span className="text-danger is-visible"></span>;
}
}
}
;
class View extends React.Component {
constructor(props) {
super(props);
this.onInputChange = this.onInputChange.bind(this);
this.sendReply = this.sendReply.bind(this);
this.toggle = this.toggle.bind(this);
this.onStatusChange=this.onStatusChange.bind(this);
this.handleEditorChange=this.handleEditorChange.bind(this);
this.state = {
response:null,
loading: false,
message:'',
status:'',
attachment1:[],
status_list:[],
formReset:true
};
}
componentDidMount() {
this.setState({formReset:true});
}
onStatusChange(event) {
this.setState({"formReset":false});
this.setState({
status: event.target.value
});
}
handleEditorChange(data) {
this.setState({"formReset":false});
this.setState({ message:data });
}
sendReply()
{
/*** code after form submission***/
}
toggle() {
}
onInputChange(event) {
event.preventDefault();
this.setState({"formReset":false});
this.setState({
[event.target.name]: event.target.value
});
}
render() {
var _this = this;
return (
<aside className="customizer">
{/*--------------------------------------------------------------------------------*/}
{/* Toggle Customizer From Here */}
{/*--------------------------------------------------------------------------------*/}
<div className="customizer-body pt-3">
<div>
{/* --------------------------------------------------------------------------------*/}
{/* Start Inner Div*/}
{/* --------------------------------------------------------------------------------*/}
<Row>
<Col md="12">
<Card>
<CardTitle className=" border-bottom p-3 mb-0">
</CardTitle>
<CardBody>
<Form ref={c => {
this.replyform = c;
}}>
<Input type="hidden" name="formReset" id="formReset" value={this.state.formReset} />
<FormGroup>
<Row>
<Label sm="2">Reply *</Label>
<Col sm="10">
<CKEditor
editor={ ClassicEditor }
data={this.state.message}
config={ {
toolbar: [ 'heading', '|', 'bold', 'italic', 'link', 'bulletedList', 'numberedList', 'blockQuote' ]
} }
onChange={ ( event, editor ) => {
const data = editor.getData();
this.handleEditorChange(data);
} }
/>
</Col>
</Row>
</FormGroup>
<FormGroup>
<Row>
<Label sm="2">Status</Label>
<Col sm="10">
<Select id="status" className="custom-select form-control" name="status" onChange={this.onStatusChange} value={this.props.status_id: null}>
<option value="">Select</option>
{this.state.status_list.map((status, index) => {
return (
<option key={index} value={status.value}>{status.label}</option>
);
})}
</Select>
</Col>
</Row>
</FormGroup>
<FormGroup>
<Row>
<Label sm="2">Attachments</Label>
<Col sm="10">
<Input
type="file"
id="attachment1" name="attachment1[]"
onChange={this.onInputChange}
multiple="multiple"
/>
</Col>
</Row>
</FormGroup>
<div className="border-top pt-3 mt-3 d-flex no-block">
<Button type="button" onClick={this.sendReply} className="btn btn-dark mr-2 ml-auto">
Send Reply
</Button>
</div>
</Form>
</CardBody>
</Card>
</Col>
</Row>
{/* --------------------------------------------------------------------------------*/}
{/* End Inner Div*/}
{/* --------------------------------------------------------------------------------*/}
</div>
</div>
</aside>
);
}
}
export default View;
Error image:
Really crazy error:
import { Formik, Form, Field } from 'formik';
above required initial values on any cost if you dont want to give initial value initialize it with empty.for example
const initialValues = {
firstname: "",
lastname: ""
}
and then in <Formik tag
initialValues={initialValues}
I was facing the same error using formik
After debugging I came to know I had a typo in the initialValues object name. Make sure you are having the same object for initalValues that you have defined. In my case I had timeCapturesInitialValues object but used timeCapturesInitailValues in the Formik prop.
after upgrading react & it's packages i was facing above issue & it's resolved by Hassan Ali Shahzad answer,
code that may help some one
<Formik
enableReinitialize={true}
initialValues={{
heatmaps: '',
}}
if your return statement is null at any given point this error occurs.
Example:
const obj = null;
return(
obj
);
Please check your code .

Resources