React - Login Error from PHP not displaying - reactjs

I am trying to display an error text message fetched from a PHP. I see from debugging that the message is returned correctly in the responseJson.message object but I'm not able to find out whether the state is updating it or why it is not rendering properly in the HTML since the page reloads itself and the input fields are emptied right after the this.setState({ error: responseJson.message }) instruction.
import React, { Component } from "react";
import { PostData } from '../../modules/PostData';
class LoginForm extends Component {
constructor() {
super()
this.state = {
error: "",
username: "",
password: ""
}
this.onSubmit = this.onSubmit.bind(this)
this.onChange = this.onChange.bind(this)
}
onSubmit() {
this.setState({ error: "" })
PostData('login', this.state).then((responseJson) => {
if (responseJson.message === "login success") {
sessionStorage.setItem('userData', JSON.stringify(responseJson));
document.location.href = `/home`
} else {
console.log(this.state.error)
this.setState({ error: responseJson.message })
}
})
}
onChange(e) {
this.setState({ [e.target.name]: e.target.value })
}
render() {
return (
<form onSubmit={this.onSubmit}>
<div>
<label htmlFor="username">Username:</label><br />
<input name="username" component="input" type="text" onChange={this.onChange}/>
</div>
<div>
<label htmlFor="password">Password:</label><br />
<input name="password" component="input" type="password" onChange={this.onChange}/>
</div>
<div>
<button type="submit">Login</button>
</div>
<div name="error" className='error' component="input" type="text" value={this.state.error}></div>
</form>
)
}
}
export default LoginForm
Thanks for the help!

There is no component, value, type attributes in div tag. In your case you should use:
<div name="error" className='error'>{this.state.error}</div>
or
<input name="error" className='error' component="input" type="text" value={this.state.error}></input>

Related

Keep getting max update exceeded error but cannot seem to find error in code

I have made forms like this before but I seem to be missing something in this one. I keep getting the error "maximum update depth exceeded error" but I dont see where I am goin wrong and I've spent too much time looking at it. I already tried to change my onChange to include an arrow because others have suggested to do so , but when that happens I cant type in the input boxes. like so
onChange={()=>this.handleChange("username")}
I should note that I only get the error when I try to register the user and not when I type into the input. Here is the full error as well.
at checkForNestedUpdates (react-dom.development.js:23804)
at scheduleUpdateOnFiber (react-dom.development.js:21836)
at Object.enqueueSetState (react-dom.development.js:12468)
at Router.Component.setState (react.development.js:366)
at react-router.js:75
at listener (history.js:156)
at history.js:174
at Array.forEach (<anonymous>)
at Object.notifyListeners (history.js:173)
at setState (history.js:562)
Here is my code, please help.
import React from "React"
class Splash extends React.Component{
constructor(props) {
super(props)
this.state = this.props.user;
this.handleSubmit = this.handleSubmit.bind(this);
}
componentDidMount() {
this.props.clearErrors();
}
handleSubmit(event) {
event.preventDefault();
this.props.signUp(this.state);
}
handleChange(field) {
return (e) => {
this.setState({ [field]: e.currentTarget.value })
};
}
render() {
return (
<div className="splash-background">
<div className="modal-screeen">
<form className="modal" onSubmit={this.handleSubmit}>
<h2 className="welcom-text"></h2>
<input className="user-input" type="text" placeholder="Name" onChange={this.handleChange("name")} value={this.state.name}/>
<input className="user-input" type="text" placeholder="Email" onChange={this.handleChange("email")} value={this.state.email}/>
<input className="user-input" type="text" placeholder="Create Username" onChange={this.handleChange("username")} value={this.state.username}/>
<input className="user-input" type="password" placeholder="Create Password" onChange={this.handleChange("password")} value={this.state.password}/>
<button>Sign Up</button>
</form>
</div>
</div>
);
}
}
export default Splash
import { connect } from "react-redux";
import { signup, login, clearErrors } from "../../actions/session_actions.js";
import Splash from "./splash";
const mapStateToProps = ({ errors }) => {
return {
errors: errors.session,
user: {
username: "",
password: "",
name:"",
email: "",
},
};
};
const mapDispatchToProps = (dispatch) => {
return {
signUp: (user) => dispatch(signup(user)),
login: (user) => dispatch(login(user)),
clearErrors: () => dispatch(clearErrors()),
};
};
export default connect(mapStateToProps, mapDispatchToProps)(Splash);
I believe the problem here is the implementation of redux and react state. If you're using redux to manage the form state then I don't think there is a need to also manage that same state with react.
Try something like this, but keep in mind this code isn't tested.
class Splash extends React.Component {
constructor(props) {
super(props);
this.handleSubmit = this.handleSubmit.bind(this);
}
componentDidMount() {
this.props.clearErrors();
}
handleSubmit(event) {
event.preventDefault();
this.props.signUp(this.props.user);
}
handleChange(e) {
// here you would have another action to update redux state depending
// on which input has changed. You can grab the input name via e.target.name
}
render() {
return (
<div className="splash-background">
<div className="modal-screeen">
<form className="modal" onSubmit={this.handleSubmit}>
<h2 className="welcom-text"></h2>
<input
className="user-input"
type="text"
placeholder="Name"
name="name"
onChange={this.handleChange}
value={this.props.user.name}
/>
<input
className="user-input"
type="text"
placeholder="Email"
name="email"
onChange={this.handleChange}
value={this.props.user.email}
/>
<input
className="user-input"
type="text"
placeholder="Create Username"
name="username"
onChange={this.handleChange}
value={this.props.user.username}
/>
<input
className="user-input"
type="password"
placeholder="Create Password"
name="password"
onChange={this.handleChange}
value={this.props.user.password}
/>
<button>Sign Up</button>
</form>
</div>
</div>
);
}
}
export default Splash;
When it comes to form data, I find it's easier to manage just with react state. Generally redux is used to manage state that is shared across the whole application/multiple components.
The problem was actually in my route util file. I had an infinite loop of rerouting!

Basic Form react

Hello I just want to make a form and my textboxes does not take my inputs and my submit works but sends no values. What am I doing wrong? I know it's a basic question but I don't know what the problem is in my code.
Key problems:
it doesn't update the state nor take my inputs.
fields editable but cant write into them
Code
import React, { Component } from "react";
class Postform extends Component {
constructor(props) {
super(props);
this.state = {
name: "",
category: "",
price: "",
};
}
changeHandler = (e) => {
this.setState = { [e.target.name]: e.target.value };
};
submitHandler = (e) => {
e.preventDefault();
console.log(this.state);
};
render() {
const { name, category, price } = this.state;
return (
<div>
<form onSubmit={this.submitHandler}>
<div>
<input
type="text"
name="name"
placeholder="Name"
value={name}
onChange={this.changeHandler}
/>
<input
type="text"
name="category"
placeholder="Category"
value={category}
onChange={this.changeHandler}
/>
<input
type="text"
name="price"
placeholder="Price"
value={price}
onChange={this.changeHandler}
/>
</div>
<button type="submit">Add product</button>
</form>
</div>
);
}
}
export default Postform;
Change this line to
changeHandler = e => {
this.setState({[e.target.name]: e.target.value });
};
Since setState is a function it is not a property !

How do I fix a component is changing from controlled input of the type text to be uncontrolled. Reactjs Error [duplicate]

This question already has answers here:
A component is changing an uncontrolled input of type text to be controlled error in ReactJS
(27 answers)
Closed 3 years ago.
I have set the initial state to blanks than why am I encountering this error ? What should I change next ?
I am fetching users from the database using ID and then trying to update their value. I get this error for the first attempt only. subsequent attempts works perfectly.
could there be problem with the backend ?
import React, { Component } from 'react';
import axios from 'axios';
export default class EditUsers extends Component {
constructor(props)
{
super(props);
this.onchangeUsername = this.onchangeUsername.bind(this);
this.onchangeAddress = this.onchangeAddress.bind(this);
this.onchangePhoneno = this.onchangePhoneno.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.state = {
username:'',
address:'',
phoneno:''
}
}
componentDidMount() {
axios.get('http://localhost:5000/users/'+this.props.match.params.id)
.then(response=>{
this.setState({
username:response.data.username,
address:response.data.address,
phoneno:response.data.phoneno,
})
})
.catch(function (error) {
console.log(error);
})
}
onchangeUsername(e)
{
this.setState({
username:e.target.value
});
}
onchangeAddress(e)
{
this.setState({
address:e.target.value
});
}
onchangePhoneno(e)
{
this.setState({
phoneno:e.target.value
});
}
onSubmit(e){
e.preventDefault();
const user =
{
username:this.state.username,
address:this.state.address,
phoneno:this.state.phoneno
}
console.log(user);
axios.post('http://localhost:5000/users/update/'+this.props.match.params.id,user)
.then(res=>console.log(res.data));
this.setState({
username:this.props.username,
address:this.props.address,
phoneno:this.props.phoneno
})
}
render()
{
return (
<div>
<h3>Edit User List</h3>
<form onSubmit={this.onSubmit}>
<div className="form-group">
<label>Username: </label>
<input type="text" required
className="form-control"
value={this.state.username}
onChange={this.onchangeUsername}
/>
</div>
<div className="form-group">
<label>Address: </label>
<input type="text" required
className="form-control"
value={this.state.address}
onChange={this.onchangeAddress}
/>
</div>
<div className="form-group">
<label>Phoneno: </label>
<input type="text" required
className="form-control"
value={this.state.phoneno}
onChange={this.onchangePhoneno}
/>
</div>
<div className="form-group">
<input type="submit" value="Update" className="btn btn-primary" />
</div>
</form>
</div>
);
}
}
Prevent your input value to be null.
If you pass from null to not null, you will recieve this error.
A quick fix could be to do this:
<input
type="text"
required
className="form-control"
value={this.state.username || ''}
onChange={this.onchangeUsername}
/>

Can't input data into form field React

Hi I am making a form can someone please tell me why i cannot seem to enter text in the input fields. I did the type "text" and i thought that usually takes care of that. Any insight would be 100% appreciated.
import React, {Component} from 'react';
class CreateExercise extends Component{
constructor(){
super()
this.onChangeUsername = this.onChangeUsername.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.state = {
username:'',
description: '',
duration: 0,
users: []
}
}
componentDidMount() {
this.setState({
users: ['test user'],
username: 'test user'
})
}
onChangeUsername(e) {
this.setState({
username: e.target.value
});
}
onChangeUsername(e) {
this.setState({
description: e.target.value
});
}
onChangeUsername(e) {
this.setState({
duration: e.target.value
});
}
onSubmit(e) {
e.preventDefault();
const exercise = ({
username: this.state.username,
description: this.state.description,
duration: this.state.duration
})
console.log(exercise)
window.location = '/';
}
render(){
return(
<div>
<h3>Create New Exercise Log</h3>
<form onSubmit={this.onSubmit}>
<div className="form-group">
<label>Username: </label>
<select ref="userInput"
required
className="form-control"
value={this.state.username}
onChange={this.onChangeUsername}>
{
this.state.users.map(function(user) {
return <option
key={user}
value={user}>{user}
</option>
})
}
</select>
</div>
<div className="form-group">
<label>Description: </label>
<input type="text"
required
className="form-control"
value={this.state.description}
onChange={this.onChangeDescription}
/>
</div>
<div className="form-group">
<label>Duration (in minutes)</label>
<input
type="text"
className="form-control"
value={this.state.duration}
onChange={this.onChangeDuration}
/>
</div>
<div className="form-group">
<input type="submit" value="Create Exercise Log" className="btn btn-primary"/>
</div>
</form>
</div>
)
}
}
export default CreateExercise;
dont use {this.state} in your value fields. Theres no need for it.
also you have 3
onChangeUsername(e) {
im guessing you might want to update the other two methods
It seems like you have some missing handlers and bindings. For example, if you add the event handler onChangeDuration:
onChangeDuration(e) {
this.setState({
duration: e.target.value
});
}
and also do the binding inside the constructor method like:
this.onChangeDuration = this.onChangeDuration.bind(this);
Your duration field should be working.
You can apply the same logic to the description field as well.
Also do not forget to remove the unnecessary onChangeUsername methods. Hope that helps.

axios put request in react is returning empty

I'm pretty new with React and Call requests. I'm building a full stack app using React, express, MySql, and Sequelize.
Everything works fine except for the Put request to edit the client information. I'm using Axios to make those calls and I can add, see, and delete data from the app but the edit part is not working.
When hitting the submit button on the form, the Put request is returning an empty array instead of the actual modified data. My routes are Ok (I believe), as testing it with Postman work just fine. I'm almost sure that my problem is on the method being used in the axios call, but I can't just find the right way to make it work. Any help would be highly appreciated.
import React, { Component } from 'react';
import axios from 'axios';
import API from '../../utils/API';
class index extends Component {
constructor(props) {
super(props);
this.onChangeLastName = this.onChangeLastName.bind(this);
this.onChangeFirstName = this.onChangeFirstName.bind(this);
this.onChangePhone = this.onChangePhone.bind(this);
this.onChangePetName = this.onChangePetName.bind(this);
this.onChangeBreed = this.onChangeBreed.bind(this);
this.onChangeNotes = this.onChangeNotes.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.state = {
client: null
}
}
componentDidMount() {
let id = this.props.match.params.id
API.getClient(id)
.then(res => {
this.setState({
client: res.data
})
console.log(this.state.client.id)
})
.catch(error => console.log(error))
}
onChangeLastName(e) {
this.setState({
lastName: e.target.value
});
}
onChangeFirstName(e) {
this.setState({
firstName: e.target.value
});
}
onChangePhone(e) {
this.setState({
phone: e.target.value
});
}
onChangePetName(e) {
this.setState({
petName: e.target.value
});
}
onChangeBreed(e) {
this.setState({
breed: e.target.value
});
}
onChangeNotes(e) {
this.setState({
notes: e.target.value
});
}
onSubmit(e) {
e.preventDefault();
let obj = {
lastName: this.state.client.lastName.value,
firstName: this.state.client.firstName.value,
phone: this.state.client.phone.value,
petName: this.state.client.petName.value,
breed: this.state.client.breed.value,
notes: this.state.client.notes.value
};
let id = this.state.client.id
axios.put("http://localhost:3000/api/clients/" + id, obj)
// .then(alert("client Updated"))
.then(res => console.log(res))
.catch(error => console.log(error))
this.props.history.push('/admin');
}
render() {
const client = this.state.client ? (
<div className="client">
<h3 style={{ marginLeft: "60px" }}>Update Client</h3>
<form onSubmit={this.onSubmit} style={{ padding: "60px" }}>
<div className="form-group">
<label>Last Name: </label>
<input type="text"
className="form-control"
defaultValue={this.state.client.lastName}
onChange={this.onChangeLastName}
/>
</div>
<div className="form-group">
<label>First Name: </label>
<input type="text"
className="form-control"
defaultValue={this.state.client.firstName}
onChange={this.onChangeFirstName}
/>
</div>
<div className="form-group">
<label>Phone: </label>
<input type="text"
className="form-control"
defaultValue={this.state.client.phone}
onChange={this.onChangePhone}
/>
</div>
<div className="form-group">
<label>Pet Name: </label>
<input type="text"
className="form-control"
defaultValue={this.state.client.petName}
onChange={this.onChangePetName}
/>
</div>
<div className="form-group">
<label>Breed: </label>
<input type="text"
className="form-control"
defaultValue={this.state.client.breed}
onChange={this.onChangeBreed}
/>
</div>
<div className="form-group">
<label>Notes: </label>
<input type="text"
className="form-control"
defaultValue={this.state.client.notes}
onChange={this.onChangeNotes}
/>
</div>
<br />
<div className="form-group">
<input type="submit" value="Update Client"
className="btn btn-primary" />
</div>
</form>
</div>
) : (
<div className="center">Loading Client</div>
)
return (
<div className="container">
{client}
</div>
)
}
}
export default index;
I am assuming it is because of the way you are handling the onchange of your inputs. You want to set the onchange to the client value in your state. But instead you are setting it to the state itself. So then when you are building your object to send to the backend you are sending null data because you haven't set any data to the actual client value in your state and it is still null. Try console logging the state and you will see what I'm talking about. Also you are adding a .value to the end each of the state values you are trying to build your object with and this is not necessary. Finally you don't need to specify an onchange for each input just give the input a name attribute and you can set your onchange handler like so:
onChange = e => {
this.setState({
[e.target.name]: e.target.value
})
}
so your component would look something like the following:
import React, { Component } from 'react';
import axios from 'axios';
import API from '../../utils/API';
class index extends Component {
constructor(props) {
super(props);
this.onChange = this.onChange.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.state = {
client: null
}
}
componentDidMount() {
let id = this.props.match.params.id
API.getClient(id)
.then(res => {
this.setState({
client: res.data
})
console.log(this.state.client.id)
})
.catch(error => console.log(error))
}
onChange(e) {
this.setState({
client: {
...this.state.client,
[e.target.name]: e.target.value
}
});
}
onSubmit(e) {
e.preventDefault();
let obj = {
lastName: this.state.client.lastName,
firstName: this.state.client.firstName,
phone: this.state.client.phone,
petName: this.state.client.petName,
breed: this.state.client.breed,
notes: this.state.client.notes
};
let id = this.state.client.id
axios.put("http://localhost:3000/api/clients/" + id, obj)
// .then(alert("client Updated"))
.then(res => console.log(res))
.catch(error => console.log(error))
this.props.history.push('/admin');
}
render() {
const client = this.state.client ? (
<div className="client">
<h3 style={{ marginLeft: "60px" }}>Update Client</h3>
<form onSubmit={this.onSubmit} style={{ padding: "60px" }}>
<div className="form-group">
<label>Last Name: </label>
<input type="text"
name="lastName"
className="form-control"
defaultValue={this.state.client.lastName}
onChange={this.onChange}
/>
</div>
<div className="form-group">
<label>First Name: </label>
<input type="text"
name="firstName"
className="form-control"
defaultValue={this.state.client.firstName}
onChange={this.onChange}
/>
</div>
<div className="form-group">
<label>Phone: </label>
<input type="text"
name="phone"
className="form-control"
defaultValue={this.state.client.phone}
onChange={this.onChange}
/>
</div>
<div className="form-group">
<label>Pet Name: </label>
<input type="text"
name="petName"
className="form-control"
defaultValue={this.state.client.petName}
onChange={this.onChange}
/>
</div>
<div className="form-group">
<label>Breed: </label>
<input type="text"
name="breed"
className="form-control"
defaultValue={this.state.client.breed}
onChange={this.onChange}
/>
</div>
<div className="form-group">
<label>Notes: </label>
<input type="text"
name="notes"
className="form-control"
defaultValue={this.state.client.notes}
onChange={this.onChange}
/>
</div>
<br />
<div className="form-group">
<input type="submit" value="Update Client"
className="btn btn-primary" />
</div>
</form>
</div>
) : (
<div className="center">Loading Client</div>
)
return (
<div className="container">
{client}
</div>
)
}
}
export default index;
It could be because you're calling this.props.history.push immediately after calling axios.post, essentially redirecting before the POST request has a chance to return a response.
Try putting this.props.history.push('/admin') inside the .then().
You are doing multiple thing wrong here,
For every input you should have only 1 onChange handler, every input have name attribute to work with state. For example,
<input type="text"
className="form-control"
defaultValue={this.state.client.lastName}
name="lastName" //Like this should add name for every input like below
onChange={this.onChangeHandler} //This is a common onChangeHandler for every input should add in every input like below
/>
<input type="text"
className="form-control"
defaultValue={this.state.client.firstName}
name="firstName"
onChange={this.onChangeHandler}
/>
And onChangeHandler function should be,
onChangeHandler(e){
this.setState({
...this.state.client,
[e.target.name]:e.target.value
})
}
And finally your onSubmit function should be,
onSubmit(e) {
e.preventDefault();
let obj = {
lastName: this.state.client.lastName, //Remove `.value` as we are getting values from state and not directly from input
firstName: this.state.client.firstName,
phone: this.state.client.phone,
petName: this.state.client.petName,
breed: this.state.client.breed,
notes: this.state.client.notes
};
let id = this.state.client.id
axios.put("http://localhost:3000/api/clients/" + id, obj)
// .then(alert("client Updated"))
.then(res => console.log(res))
.catch(error => console.log(error))
this.props.history.push('/admin');
}
Note: You won't get value here in console.log,
API.getClient(id)
.then(res => {
this.setState({
client: res.data
})
console.log(this.state.client.id)
})
beacuse seState is async, you should use callback in setState to make console.log,
API.getClient(id)
.then(res => {
this.setState({
client: res.data
}, () => console.log(this.state.client.id)) //This is callback
})

Resources