React Js Login Beginner - reactjs

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;

Related

React, Material UI: Submit button not working on mobiles

My react component Login controls user login functionality. I have a material UI submit button which posts the users credentials. It works fine, except on mobiles - when users are on their phones, the submit button doesn't work and the onClick event is not fired. Any suggestions on how to make it work?
Here's the login component:
import React from 'react'
import Header from './Header'
import TextField from "#material-ui/core/TextField";
import Button from '#material-ui/core/Button'
import {Link} from 'react-router-dom'
import firebase from 'firebase'
import {auth} from 'firebase/app'
class Login extends React.Component {
constructor() {
super();
this.state = {
email: "",
password: "",
errors:[]
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(e) {
this.setState({
[e.target.name]: e.target.value,
});
}
handleSubmit(e) {
e.preventDefault()
const { email, password } = this.state
const { history } = this.props
const errorLog = []
auth().signInWithEmailAndPassword(email, password)
.then((res) => {
history.push('/gigregister')
console.log(`token: ${res.data.user.getIdToken()}`)
})
.catch((err) => {
if(err.code === 'auth/wrong-password'){
errorLog.push('Wrong credentials, please try again')
this.setState({
errors: errorLog
})
}
})
}
render() {
return (
<>
<div>
<Header />
</div>
<div className = 'login-container'>
<div className ='gig-button'>
<Link to="/Homepage" style={{ textDecoration: "none" }}>
<button className = 'gig-button-button'>Gigs this week</button>
</Link>
</div>
<div className="login-main">
<div className="login">
<h4>Venue login</h4>
<h5>Not registered? Sign up <Link to="/venueregister" style={{ textDecoration: "none" }}>here</Link></h5>
<form onSubmit={this.handleSubmit}>
<TextField
placeholder="Enter email"
id="email"
name="email"
onChange={this.handleChange}
/>
<TextField
placeholder="Enter password"
id="password"
name="password"
error ={this.state.errors ? true : false}
errorText = {this.state.errors}
helperText = {this.state.errors}
onChange={this.handleChange}
type ='password'
/>
<div className="button">
<Button type="submit">Submit</Button>
</div>
</form>
</div>
</div>
</div>
</>
);
}
}
export default Login;
You need to add cursor:'pointer' to your button's CSS rules. This allows the mobile devices recognise a button press and fire a click event instead.
You'll find more information in this GitHub issue here.
Hope this answer helps!

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

'ControlLabel' is not exported from 'react-bootstrap'

Hello I'm creating a login form in react, to check the login parameters use Checkbel of the package, but when I run the code I'm thrown this exception: ./src/App.js Attempted import error: 'ControlLabel' is not exported from 'react-bootstrap'. how do I solve?
React Code:
import React, { Component } from "react";
import { Form,Button, FormGroup, FormControl, ControlLabel } from "react-bootstrap";
import "./Login.css";
import Bootstrap from "react-bootstrap";
export default class Login extends Component {
constructor(props) {
super(props);
this.state = {
email: "",
password: ""
};
}
validateForm() {
return this.state.email.length > 0 && this.state.password.length > 0;
}
handleChange = event => {
this.setState({
[event.target.id]: event.target.value
});
}
handleSubmit = event => {
event.preventDefault();
}
render() {
return (
<div className="Login">
<form onSubmit={this.handleSubmit}>
<FormGroup controlId="email" bsSize="large">
<ControlLabel>Email</ControlLabel>
<FormControl
autoFocus
type="email"
value={this.state.email}
onChange={this.handleChange}
/>
</FormGroup>
<FormGroup controlId="password" bsSize="large">
<ControlLabel>Password</ControlLabel>
<FormControl
value={this.state.password}
onChange={this.handleChange}
type="password"
/>
</FormGroup>
<Button
block
bsSize="large"
disabled={!this.validateForm()}
type="submit"
>
Login
</Button>
</form>
</div>
);
}
}
Try FormLabel instead of ControlLabel.
<ControlLabel> is from an older version of react-bootstrap. The current version ("react-bootstrap": "^1.4.3") uses <FormLabel> or <Form.Label>
According to this url https://react-bootstrap.github.io/components/buttons/#button-props and your version you should modify your code like this.
import React, { Component } from "react";
import Form from 'react-bootstrap/Form'
import Button from 'react-bootstrap/Button'
import Bootstrap from "react-bootstrap";
export default class Login extends Component {
constructor(props) {
super(props);
this.state = {
email: "",
password: ""
};
}
validateForm() {
return this.state.email.length > 0 && this.state.password.length > 0;
}
handleChange = event => {
this.setState({
[event.target.id]: event.target.value
});
}
handleSubmit = event => {
event.preventDefault();
}
render() {
return (
<div className="Login">
<Form onSubmit={this.handleSubmit}>
<Form.Group controlId="email" bsSize="large">
<Form.Control
autoFocus
type="email"
value={this.state.email}
onChange={this.handleChange}
/>
</Form.Group>
<Form.Group controlId="password" bsSize="large">
<Form.Control
value={this.state.password}
onChange={this.handleChange}
type="password"
/>
</Form.Group>
<Button
block
bsSize="large"
disabled={!this.validateForm()}
type="submit"
>
Login
</Button>
</Form>
</div>
);
}
}
This "react-bootstrap": "^1.0.0-beta.16", doesn't contain the ControlLabel, so
uninstall it using
npm uninstall react-bootstrap
and then re install with this "react-bootstrap": "^0.32.4" version
npm install react-bootstrap#0.32.4 --save
will definitely fix this issue

redux-form v6: Form submission canceled because the form is not connected

I am getting this error in my console.
"Form submission canceled because the form is not connected"
after trying to migrate my redux-form from v5 to v6 since we migrated our app to a more recent version of React.
I am not sure what is going wrong here so i figured I could use a second or third pair of eyes.
Here is my "Smart Component"
import React, { PropTypes } from 'react';
import { reduxForm } from 'redux-form/immutable';
import { connect } from 'react-redux';
import { logUserIn } from '../../actions/authentication';
import { VALID_EMAIL_REGEX } from '../../config/app_config';
import LoginForm from './LoginForm';
const FORM_ID = 'loginForm';
export class LoginFormContainer extends React.Component {
static propTypes = {
handleSubmit: PropTypes.func.isRequired,
submitting: PropTypes.bool.isRequired,
loginAction: PropTypes.func.isRequired,
};
performLogin = (params) => {
const { loginAction } = this.props;
const credentials = {
email: params.email,
password: params.password,
};
loginAction(credentials, '/home');
}
render() {
const { handleSubmit, submitting } = this.props;
return (
<LoginForm
handleSubmit={ handleSubmit }
loginFunction={ this.performLogin }
submitting={ submitting }
/>
);
}
}
const validate = values => {
const errors = {};
if (!values.email || values.email === '') {
errors.email = 'Required';
}
else if (!VALID_EMAIL_REGEX.test(values.email)) {
errors.email = 'Invalid email address';
}
if (!values.password || values.password === '') {
errors.password = 'Required';
}
return errors;
};
LoginFormContainer = reduxForm({
form: FORM_ID,
validate,
})(LoginFormContainer);
export default connect(null, {
loginAction: logUserIn,
})(LoginFormContainer);
I am passing down my submission handler function as a prop to my actual form that contains the Field component for inputs. The loginAction will link to the action for redux to send the values to the backend and redirect to home.
import React, { PropTypes } from 'react';
import { Field } from 'redux-form/immutable';
import { getClassName, checkButtonDisabled } from '../../utils/forms';
import { Link } from 'react-router';
const renderInput = (field) => {
return (
<div className={ getClassName(field.meta.touched, field.meta.error) }>
<input
{...field.input}
className="form-control form-control-success"
type={field.type}
/>
{field.meta.touched &&
field.meta.error &&
<span className="error">{field.meta.error}</span>}
</div>
);
};
export default class LoginForm extends React.Component {
static propTypes = {
handleSubmit: PropTypes.func.isRequired,
loginFunction: PropTypes.func.isRequired,
submitting: PropTypes.bool.isRequired,
};
render() {
const {
loginFunction,
submitting } = this.props;
return (
<form onSubmit={ loginFunction.bind(this) }>
<fieldset>
<div>
<label className="form-control-label">
Email address
</label>
<Field
name="email"
component={renderInput}
type="text"
placeholder="example#exampledomain.com"
/>
</div>
<div>
<label className="form-control-label">
Password
</label>
<Field
name="password"
component={renderInput}
type="password"
placeholder="your password"
/>
</div>
</fieldset>
<button
type="submit"
className="btn btn-primary"
disabled={ checkButtonDisabled(submitting) }
>
Log In
</button>
<Link to="/forgot-password">Forgot Password?</Link>
</form>
);
}
}
I successfully was able to get the form to work but when I hit login I get the error above and I am redirected to home, but I am not authenticated and I get a 422 error as well. I couldn't tell if my form connecting is the only error or if my action is not getting the right information from the form submission function.
Got any suggestions?
You are redirected home, because your loginFunction() is fired, but the form is not submitted
There are a couple of things that need to be updated. Your <form> tag must have a corresponding id and it should handle submit by passing your function to redux-form inbuilt submit handler. So you modifying LoginForm class as follows should get the form working
<form id="loginForm" onSubmit={ handleSubmit(this.loginFunction.bind(this)) } >
More about internal redux-form method handleSubmit here: http://redux-form.com/6.5.0/docs/api/Form.md/
Using the answer given to me above I just wanted to clarify what I did to solve the issue.
I grabbed the handleSubmit method that comes from the reduxForm and passed it to the LoginForm as a prop from the container that also retrieved it from the props.
I also imported the Form component from redux-form on the LoginForm component and just simply replaced the normal JSX tag with .
here were the final changes I made.
LoginForm.jsx:
//Added Form from redux-form
import { Field, Form } from 'redux-form/immutable';
render() {
const {
handleSubmit,//defined handleSubmit function from props which comes from the reduxForm being exported to the state.
loginFunction,
submitting } = this.props;
return (
//replaced <form></form> with <Form></Form>
<Form id="loginForm" onSubmit={ handleSubmit(loginFunction.bind(this)) }>
//passed my loginFunction into the handleSubmit function
//added an id to <Form> that corresponds to the forms id that was passed in reduxForm({ form: 'loginForm' })
<fieldset>
<div>
<label className="form-control-label">
Email address
</label>
<Field
name="email"
component={renderInput}
type="text"
placeholder="example#exampledomain.com"
/>
</div>
<div>
<label className="form-control-label">
Password
</label>
<Field
name="password"
component={renderInput}
type="password"
placeholder="your password"
/>
</div>
</fieldset>
<button
type="submit"
className="btn btn-primary"
disabled={ checkButtonDisabled(submitting) }
>
Log In
</button>
<Link to="/forgot-password">Forgot Password?</Link>
</Form>
);

react-bootstrap - login form - Uncaught TypeError

I have the following login.js
import React, { Component, PropTypes } from 'react';
import { Button, Form, FormControl, FormGroup } from 'react-bootstrap';
export default class Login extends Component {
render() {
const {errorMessage} = this.props
return (
<Form inline>
<FormGroup controlId="formInlineEmail">
<FormControl type="email" ref="username" placeholder="Email"/>
</FormGroup>
<FormGroup controlId="formInlinePassword">
<FormControl type="password" ref="password"/>
</FormGroup>
<Button type="submit" onClick={(event) => this.handleClick(event)}>
Login
</Button>
{errorMessage &&
<p style={{color:'red'}}>{errorMessage}</p>
}
</Form>
)
}
handleClick(event) {
const username = this.refs.username
const password = this.refs.password
const creds = { username: username.value.trim(), password: password.value.trim() }
this.props.onLoginClick(creds)
}
}
Login.propTypes = {
onLoginClick: PropTypes.func.isRequired,
errorMessage: PropTypes.string
}
When attempting to login I get the following error:
Uncaught TypeError: (0, _reactDom2.default) is not a function at Login.handleClick
if I avoid using react-bootstrap and do the following in my Login.js it works fine.
<div>
<input type='text' ref='username' className="form-control" style={{ marginRight: '5px' }} placeholder='Username'/>
<input type='password' ref='password' className="form-control" style={{ marginRight: '5px' }} placeholder='Password'/>
<button onClick={(event) => this.handleClick(event)} className="btn btn-primary">
Login
</button>
{errorMessage &&
<p style={{color:'red'}}>{errorMessage}</p>
}
</div>
Don't ask why but this works:
import React, { Component, PropTypes } from 'react';
import { findDOMNode } from 'react-dom';
import { Button, ControlLabel, Form, FormControl, FormGroup } from 'react-bootstrap';
export default class Login extends Component {
handleSubmit(event) {
const username = findDOMNode(this.refs.username)
const password = findDOMNode(this.refs.password)
const creds = { username: username.value.trim(), password: password.value.trim() }
this.props.onLoginClick(creds)
}
render() {
const {errorMessage} = this.props
return (
<Form inline>
<FormGroup controlId="formHorizontalEmail">
<ControlLabel>Email </ControlLabel>
<FormControl type="username" ref="username" onChange={this.handleChange} placeholder="Email" />
</FormGroup>
<FormGroup controlId="formHorizontalPassword">
<ControlLabel>Password </ControlLabel>
<FormControl type="password" ref="password" onChange={this.handleChange} placeholder="Password" />
</FormGroup>
<Button onClick={(event) => this.handleSubmit(event)}>Login</Button>
{errorMessage &&
<p style={{color:'red'}}>{errorMessage}</p>
}
</Form>
)
}
}
Login.propTypes = {
onLoginClick: PropTypes.func.isRequired,
errorMessage: PropTypes.string
}

Resources