Cannot Get ReactJS Component to Update - javascript

I'm attempting to update an area on my page once a fetch() call has been made with the resulting error message from the fetch() call. The fetch() call is executed when the form button is submitted.
When fetch() has completed, I have written ErrorMessage(data['Result']); which I thought would pass data['Result'] as the props. You can see in my render that I have <ErrorMessage error="Original Message" /> which is what I thought would update with the message from the fetch() call.
Please see my full code below for this page:
import React from 'react';
import './css/LoginForm.css';
function ErrorMessage(props) {
return (
<p id="error-message">
{props.error}
</p>
)
}
class LoginForm extends React.Component {
constructor(props) {
super(props);
this.state = {
username: '',
password: ''
};
this.handleInputChange = this.handleInputChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleInputChange(event) {
const target = event.target;
const value = target.value;
const name = target.name;
this.setState({
[name]: value
});
}
handleSubmit(event) {
event.preventDefault();
var loginData = {
username: this.state.username,
password: this.state.password
}
fetch('/login', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
loginData: loginData
})
})
.then(function(response) {
return response.json();
})
.then(function(data) {
if (data['Result']) {
console.log(data['Result']);
ErrorMessage(data['Result']);
}
})
.catch(function(error) {
console.log('Error: ', error);
});
}
render() {
return (
<div id="login-form-container">
<form id="login-form" onSubmit={this.handleSubmit} method="POST">
<ErrorMessage error="Original Message" />
<input
type="text"
name="username"
placeholder="username"
autoComplete="username"
onFocus={(e) => e.target.placeholder = ''}
onBlur={(e) => e.target.placeholder = 'username'}
value={this.state.username}
onChange={this.handleInputChange}
required
></input>
<input
type="password"
name="password"
placeholder="password"
autoComplete="current-password"
onFocus={(e) => e.target.placeholder = ''}
onBlur={(e) => e.target.placeholder = 'password'}
value={this.state.password}
onChange={this.handleInputChange}
required
></input>
<button type="submit" name="submit">Login</button>
<p className="forgotten-password">Forgotten your password?</p>
</form>
</div>
);
}
}
export default LoginForm;
This may be completely wrong as I am struggling to understand exactly how a component works in ReactJS, so I apologise in advance. Thank you for any insight.

Creating a component when your fetch is complete will not affect what is returned from the render method of your LoginForm component.
You could instead set the error message in the LoginForm state, and use that as props for the ErrorMessage component in the render method.
Example
class LoginForm extends React.Component {
constructor(props) {
super(props);
this.state = {
username: "",
password: "",
error: "Original Message"
};
this.handleInputChange = this.handleInputChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
// ...
handleSubmit(event) {
event.preventDefault();
var loginData = {
username: this.state.username,
password: this.state.password
};
fetch("/login", {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify({
loginData: loginData
})
})
.then((response) => {
return response.json();
})
.then((data) => {
if (data["Result"]) {
console.log(data["Result"]);
this.setState({ error: data["Result"] });
}
})
.catch((error) => {
console.log("Error: ", error);
});
}
render() {
return (
<div id="login-form-container">
<form id="login-form" onSubmit={this.handleSubmit} method="POST">
<ErrorMessage error={this.state.error} />
<input
type="text"
name="username"
placeholder="username"
autoComplete="username"
onFocus={e => (e.target.placeholder = "")}
onBlur={e => (e.target.placeholder = "username")}
value={this.state.username}
onChange={this.handleInputChange}
required
/>
<input
type="password"
name="password"
placeholder="password"
autoComplete="current-password"
onFocus={e => (e.target.placeholder = "")}
onBlur={e => (e.target.placeholder = "password")}
value={this.state.password}
onChange={this.handleInputChange}
required
/>
<button type="submit" name="submit">
Login
</button>
<p className="forgotten-password">Forgotten your password?</p>
</form>
</div>
);
}
}

Related

React form onSubmit function not being called

I have a form on my page with an onSubmit function that I want to be called, but it doesn't seem to be triggered as the console.log never appears.
import React, { Component } from 'react'
class EmailSignUp extends Component {
constructor(props) {
super(props)
this.state = {
email: '',
lastName: '',
error: false
}
this.handleChange = this.handleChange.bind(this)
this.onSubmitForm = this.onSubmitForm.bind(this)
}
onSubmitForm (e) {
console.log('function has run');
e.preventDefault()
let formData = new FormData(e)
const { formAction } = this.props
const requestOptions = {
method: 'POST',
body: formData
}
fetch(formAction, requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error))
}
handleChange (e) {
const value = e.target.value
const inputId = e.target.id
this.setState(() => ({
[inputId]: value
}))
}
render () {
const { error } = this.state
return (
<div id='email-form' className='container'>
<form
name='form'
id='form'
onSubmit={this.onSubmitForm}
method='post'
>
<div className='form-group'>
<label htmlFor='email'>Email</label>
<input
type='email'
name='Email'
className='form-control'
id='email'
placeholder='youremail#email.com'
onChange={this.handleChange}
value={this.state.email}
required
/>
</div>
<div className='form-group'>
<label htmlFor='lastName'>Last name</label>
<input
type='text'
name='lastName'
className='text form-control'
id='lastName'
placeholder='Last Name'
onChange={this.handleChange}
value={this.state.lastName}
required
/>
</div>
<button
type='submit'
name='Submit'
value='Subscribe'
className='btn btn-primary item_cta'
readOnly
/>
</form>
{error && <p>{error}</p>}
</div>
)
}
}
export default EmailSignUp
Running your code results in the error 'Failed to construct 'FormData': parameter 1 is not of type 'HTMLFormElement'. The actual form element would be on target of the submit event. Try the following by updating e to e.target:
let formData = new FormData(e.target);
const { formAction } = this.props;
Also remove method from the form element. In addition, remove readOnly from button. It is not meant to be a self closing element like a br:
<button
type="submit"
name="Submit"
value="Subscribe"
className="btn btn-primary item_cta"
>submit</button>
Hopefully that helps!

AXIOS PUT request returns a 200 code but doesn't update content?

So I have a a component that returns a 200 code but for some reason the content does not update at all after I click the submit button. My goal is to update the 4 divs inside the form after submitting the form. The course state contains properties that contain info about each course, those properties are _id, description, estimatedTime, materialsNeeded and title.
Can someone help?
class UpdateCourse extends Component {
constructor(props) {
super(props);
this.state = {
course: []
};
this.handleSubmit = this.handleSubmit.bind(this);
}
change = e => {
this.setState({
[e.target.name]: e.target.value
});
};
handleSubmit = event => {
const {
match: { params }
} = this.props;
event.preventDefault();
const updateCourse = {
title: this.state.course.title,
description: this.state.course.description,
estimatedTime: this.state.course.estimatedTime,
materialsNeeded: this.state.course.materialsNeeded
};
axios({
method: "put",
url: `http://localhost:5000/api/courses/${params.id}`,
auth: {
username: window.localStorage.getItem("Email"),
password: window.localStorage.getItem("Password")
},
data: updateCourse
})
.then(response => {
//if the response came back as 204 then alert the user that the course was successfully updated, if another code came back then redirect them to the error handler
if (response.status === 204) {
alert("The course has been successfully updated!");
this.props.history.push("/");
} else {
throw new Error();
}
})
.catch(err => {
//use a catch method to catch the errors and display them is the status code comes back as 400
console.log("CATCH =", err.response.data.errors);
this.setState({
//if there were errors, then set the errors state in react to the error messages that came from the REST API
errors: err.response.data.errors
});
});
};
componentDidMount() {
const {
match: { params }
} = this.props;
axios
.get(`http://localhost:5000/api/courses/${params.id}`)
.then(results => {
this.setState({
course: results.data
});
});
}
render() {
return (
<div>
<div>
<form onSubmit={this.handleSubmit}>
<div>
<input
id="title"
name="title"
type="text"
className="input-title course--title--input"
placeholder="Course title..."
defaultValue={this.state.course.title}
onChange={e => this.change(e)}
/>
</div>
<div>
<textarea
id="description"
name="description"
placeholder={this.state.course.description}
defaultValue={this.state.course.description}
onChange={e => this.change(e)}
/>{" "}
</div>
<div>
<input
id="estimatedTime"
name="estimatedTime"
type="text"
className="course--time--input"
placeholder="Hours"
defaultValue={this.state.course.estimatedTime}
onChange={e => this.change(e)}
/>
</div>
<div>
<textarea
id="materialsNeeded"
name="materialsNeeded"
placeholder={this.state.course.materialsNeeded}
defaultValue={this.state.course.materialsNeeded}
onChange={e => this.change(e)}
/>
</div>
</form>
</div>
</div>
);
}
}
Please update with this:
constructor(props) {
super(props);
this.state = {
course: {}
};
this.handleSubmit = this.handleSubmit.bind(this);
this.change = this.change.bind(this);
}
change = e => {
const obj = { [e.target.name]: e.target.value };
const course = Object.assign({}, this.state.course, obj);
this.setState({
course
});
};

How can I redirect to correct page when successfully submitting form information?

As of now, I'm successfully inserting information into the database (SQL, phpMyAdmin) via Home.js but the problem is that every time the user enters information & hits submit, it gets redirected to my demo.php file (not provided) instead of Next.js.
In other words, how can I make it so that upon the user information successfully entering the database and go to the next page? (Next.js)?
What am I doing wrong and how can I fix this?
Here's Home.js:
import React, { Component } from 'react';
import Next from '../Home/Next';
class Home extends Component {
constructor(props) {
super(props);
this.state = {
show: false
};
this.getPHP = this.getPHP.bind(this);
this.goNext = this.goNext.bind(this);
}
getPHP() {
fetch(`http://localhost/demo_react/api/demo.php`, {
method: 'POST'
}).then(res => res.json())
.then(response => {
console.log('response');
console.log(response);
});
}
goNext() {
this.setState({show: true});
}
render() {
const next = this.state.show;
if(next) {
return <Next/>;
}
return (
<div>
<br/>
<form className="form-control" action="http://localhost/demo_react/api/demo.php" method={"POST"} encType="multipart/form-data">
<input type="text" name="username"/>
<input type="text" name="password"/>
<input type="submit" value="submit" onClick={this.getPHP & this.goNext} name={"submit"}/>
</form>
</div>
);
}
}
export default Home;
Here's Next.js:
import React, { Component } from 'react';
class Next extends Component {
render() {
return(
<h1>made it</h1>
);
}
}
export default Next;
You need to remove the action property from your form and call getPHP() when form is submitted. Also, it's better to have controlled inputs (state of component change when input change). See this for more info: Get form data in Reactjs
<form className="form-control" onSubmit={e => this.getPHP(e)}>
<input type="text" name="username" value={this.state.username} onChange={e => this.setState({ username: e.target.value })} />
<input type="text" name="password" value={this.state.password} onChange={e => this.setState({ password: e.target.value })} />
<input type="submit" value="submit" name="submit" />
</form>
You can access to form values directly in getPHP() method because inputs are now controlled:
constructor(props) {
super(props);
this.state = {
show: false,
username: '',
password: '',
};
}
getPHP(e) {
e.preventDefault();
const { username, password } = this.state;
const formData = new FormData();
formData.append('username', username);
formData.append('password', password );
fetch(`http://localhost/demo_react/api/demo.php`, {
method: 'POST',
headers: new Headers({ 'Content-Type': 'multipart/form-data' }),
body: formData,
})
.then(res => res.json())
.then(response => {
console.log('response');
console.log(response);
this.goNext();
});
}
At the end, you can goNext() when the fetch succeed.

How can I get the data of form on submit?

How can I get the data of form on submit?
import React, { Component } from 'react';
import Axios from 'axios';
class Register extends Component {
submitHandler = (event) => {
event.preventDefault();
var url = '';
var data = {
returnSecureToken:true,
email:this.email,
password:this.password
}
Axios.post(url,data)
.then(response => {
console.log(response);
})
.catch(err =>{
console.log(err);
})
}
render() {
var listClasses = "";
return(
<div>
<h1>Registrati</h1>
<form onSubmit={this.submitHandler}>
<input type="password" className={listClasses} value={this.props.value} placeholder="password" name="password"/>
<input type="email" className={listClasses} value={this.props.value} placeholder="email" name="email"/>
<input type="submit" value="submit"/>
</form>
</div>
);
}
}
export default Register;
I want to send my data by post. I tried to find into my object this but I don't see my data after submit.
The best way to do it is to make the component, uncontrolled component and hook up the change event handlers for each field.
Would be better than using refs that break the encapsulation.
import React, { Component } from 'react';
import Axios from 'axios';
class Register extends Component {
state = {
emailAddress: '',
password: ''
}
submitHandler = (event) => {
const {
emailAddress,
password
} = this.state;
event.preventDefault();
var url = '';
var data = {
returnSecureToken: true,
email: emailAddress,
password: password
}
Axios.post(url, data)
.then(response => {
console.log(response);
})
.catch(err => {
console.log(err);
})
}
handlePasswordChange = (event) => {
this.setState({ password: event.target.value });
}
handleEmailChange = (event) => {
this.setState({ emailAddress: event.target.value });
}
render() {
var listClasses = "";
return (
<div>
<h1>Registrati</h1>
<form onSubmit={this.submitHandler}>
<input onchange={this.handlePasswordChange} type="password" className={listClasses} value={this.props.value} placeholder="password" name="password" />
<input onchange={this.handleEmailChange} type="email" className={listClasses} value={this.props.value} placeholder="email" name="email" />
<input type="submit" value="submit" />
</form>
</div>
);
}
}
export default Register;

React Redux action not dispatched but request is successful

I'm trying to implement authentication on my project, as title says it registers an user but actions are not dispatched. I have almost the same action for fetching data, it works, dispatches the actions. is the function:
export const signIn = data => dispatch => {
dispatch({
type: SIGN_UP
})
fetch(API_URL+'/register', {
method: 'POST',
headers: {
'content-type': 'application/json'
},
body: JSON.stringify(data),
})
.then(response => response.json())
.then(message => dispatch({
type: SIGN_UP_SUCCESS, payload: message
}))
.catch(error => dispatch({
type: SIGN_UP_FAILED, payload: error
}))
}
Reducer:
export const authReducer = (state = initialState, action) => {
switch(action.type) {
case SIGN_UP:
return {
...state,
loading: true
}
case SIGN_UP_SUCCESS:
return {
...state,
loading: false,
message: action.payload
}
case SIGN_UP_FAILED:
return {
...state,
loading: false,
error: action.payload
}
default:
return state
}
}
connect method:
export default connect(null, { signIn })(RegisterForm);
Register Form component code(just to satisfy Stackoverflow's wishes):
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { Form, Button, Message, Field } from 'semantic-ui-react';
import validator from 'email-validator';
import { signUp } from '../../actions/authActions';
class RegisterForm extends React.Component {
constructor(props) {
super(props)
this.state = {
data: {
username: '',
name: '',
email: '',
password: '',
city: '',
address: ''
},
errors: {}
}
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange = e => {
this.setState({
...this.state,
data: { ...this.state.data, [e.target.name]: e.target.value}
})
}
handleSubmit = e => {
console.log(this.state.data)
e.preventDefault();
const errs = this.validate(this.state.data);
this.setState({
errors: errs
});
if(Object.keys(this.state.errors).length === 0) {
this.props.signUp(this.state.data)
}
}
validate = data => {
const errors = {};
if(!data.username) errors.username = 'Username is required';
if(!data.name) errors.name = 'Name is required';
if(!data.email) errors.email = 'Email is required';
if (!validator.validate(data.email)) errors.email = "Invalid email";
if(!data.password) errors.password = 'Password is required';
if(!data.city) errors.city = 'City is required';
if(!data.address) errors.address = 'Address is required'
return errors
}
render() {
const { errors, data } = this.state
return <Form onSubmit={this.handleSubmit}>
<Form.Field>
<label>Username</label>
<input
placeholder='Username'
name="username"
type="text"
onChange={this.handleChange}
value={this.state.data.username}
/>
</Form.Field>
{errors.username && <Message error header={errors.username}/>}
<Form.Field>
<label>Name</label>
<input
placeholder='Name'
name="name"
type="text"
onChange={this.handleChange}
value={this.state.data.name}
/>
</Form.Field>
{errors.name && <Message error header={errors.name}/>}
<Form.Field>
<label>Address</label>
<input
placeholder='Address'
name="address"
type="text"
onChange={this.handleChange}
value={this.state.data.address}
/>
</Form.Field>
{errors.address && <Message error header={errors.address}/>}
<Form.Field>
<label>City</label>
<input
placeholder='City'
name="city"
type="text"
onChange={this.handleChange}
value={this.state.data.city}
/>
</Form.Field>
{errors.city && <Message error header={errors.city}/>}
<Form.Field>
<label>Email</label>
<input
placeholder='Email'
name="email"
type="email"
onChange={this.handleChange}
value={this.state.data.email}
/>
</Form.Field>
{errors.email && <Message error header={errors.email}/>}
<Form.Field>
<label>Password</label>
<input
placeholder='Password'
name="password"
type="password"
onChange={this.handleChange}
value={this.state.data.password}
/>
</Form.Field>
{errors.password && <Message error header={errors.password}/>}
<Button type='submit'>Register</Button>
</Form>
}
}
export default connect(null, { signUp })(RegisterForm);
Your code seems to be fine, make sure your redux-devtools is implemented correctly.
const store = createStore(reducer, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__(), applyMiddleware(thunk)) // [, rest of middlewares]
Did you use bindActionCreators inside your component? in handleSubmit you just called action without dispatching it

Categories

Resources