How do I redirect to another page on form submit? - reactjs

I'm trying to redirect to a certain page once I post my form but it doesn't redirect, it only posts the form data and does not redirect to the stated page
I've tried appending the && operator in order for onSubmit to do both functions but to no avail. I also tried having both "onSubmit" and "onClick" but it's only "onSubmit" that works
//./userspost.js
import React, { Component } from "react";
import { Redirect, Link } from "react-router-dom";
import Form1 from "./form1";
import { createUsers } from "./actions/appactions";
class userspost extends Component {
state = {
redirect: false
};
setRedirect = () => {
this.setState({
redirect: true
});
};
renderRedirect = () => {
if (this.state.redirect) {
return <Redirect to="/users" />;
}
};
handleSubmit(data) {
console.log("form submission data", data);
createUsers(data);
}
render() {
return (
<div>
{this.renderRedirect()}
<Form1 onSubmit={this.handleSubmit && this.setRedirect} />
</div>
);
}
}
export default userspost;
for the posting the form data
//./form1.js
import React from "react";
import { Link } from "react-router-dom";
var createReactClass = require("create-react-class");
const Form1 = createReactClass({
//setting initial state
getInitialState() {
return {
firstName: this.props.firstName,
lastName: this.props.lastName,
userName: this.props.userName,
role: this.props.role
};
},
handleFirstChange(e) {
this.setState({
firstName: e.target.value
});
},
handleLastChange(e) {
this.setState({
lastName: e.target.value
});
},
handleUserChange(e) {
this.setState({
userName: e.target.value
});
},
handleRoleChange(e) {
this.setState({
role: e.target.value
});
},
handleSubmit(e) {
e.preventDefault();
this.props.onSubmit(this.state);
},
render() {
return (
<form
name="categories_post"
className="form-horizontal"
onSubmit={this.handleSubmit}
>
<div id="categories_post">
<div className="form-group">
<label
className="col-sm-2 control-label required"
htmlFor="firstName"
>
First Name
</label>
<div className="col-sm-10">
<input
type="text"
value={this.state.firstName}
onChange={this.handleFirstChange}
id="firstName"
required="required"
className="form-control"
/>
</div>
</div>
<div className="form-group">
<label
className="col-sm-2 control-label required"
htmlFor="lastName"
>
Last Name
</label>
<div className="col-sm-10">
<input
type="text"
value={this.state.lastName}
onChange={this.handleLastChange}
id="lastName"
required="required"
className="form-control"
/>
</div>
</div>
<div className="form-group">
<label
className="col-sm-2 control-label required"
htmlFor="userName"
>
UserName
</label>
<div className="col-sm-10">
<input
type="text"
value={this.state.userName}
onChange={this.handleUserChange}
id="userName"
required="required"
className="form-control"
/>
</div>
</div>
<div className="form-group">
<label className="col-sm-2 control-label required" htmlFor="role">
Role
</label>
<div className="col-sm-10">
<input
type="text"
value={this.state.role}
onChange={this.handleRoleChange}
id="role"
required="required"
className="form-control"
/>
</div>
</div>
<div className="form-group">
<div className="col-sm-2" />
<div className="col-sm-10">
<button
type="submit"
id="categoriesSubmit"
className="btn-default btn"
>
submit
</button>
</div>
</div>
<div className="form-group">
<div className="col-sm-2" />
<div className="col-sm-10">
<button className="btn btn-danger">
<Link to="/users">Home</Link>
</button>
</div>
</div>
</div>
</form>
);
}
});
export default Form1;
for posting using the fetch API
//./actions/appactions.js
import fetch from "isomorphic-fetch";
export function createCategories(data) {
return fetch("https://localhost:44341/api/categories", {
method: "POST",
mode: "cors",
body: JSON.stringify(data),
headers: {
"Content-Type": "application/json"
}
})
.then(res => {
return res;
})
.catch(err => err);
}
export function createUsers(data) {
return fetch("https://localhost:44341/api/users/create", {
method: "POST",
mode: "cors",
body: JSON.stringify(data),
headers: {
"Content-Type": "application/json"
}
})
.then(res => {
return res;
})
.catch(err => err);
}
export function createBusiness(data) {
return fetch("https://localhost:44341/api/businesslistings/create", {
method: "POST",
mode: "cors",
body: JSON.stringify(data),
headers: {
"Content-Type": "application/json"
}
})
.then(res => {
return res;
})
.catch(err => console.log(err));
}

The issue is that you are rendering the Redirect component along with the rest of your JSX everytime. Rendering only <Redirect to="" /> should solve your problem.
class userspost extends Component {
state = {
redirect: false
};
setRedirect = () => {
this.setState({
redirect: true
});
};
handleSubmit(data) {
console.log("form submission data", data);
createUsers(data);
}
render() {
if( this.state.redirect ){
return <Redirect to="users/" />
}
return (
<div>
{this.renderRedirect()}
<Form1 onSubmit={this.handleSubmit} />
</div>
);
}
}
Also, use only the handleSubmit function in your form onSubmit event. Since adding two functions with && could cause unexpected results. And when everything is ready to redirect, just call your function setRedirect.
There is someone that already answered something similar, so I took a bit of help from there. Check it out:
https://stackoverflow.com/a/43230829/5568741

Related

Sending email using react and nodemailer

Been trying to make a contact form which uses nodemailer. I used Postman to check if my backend is working, and it is. I even get an email in my outlook. However, I am stuck at the front end bit. I just can't seem to get the actual contact form to send an email on submit. My code is below.
Backend
app.use(express.json());
app.use(bodyParser.json());
app.use(cors());
app.use(express.urlencoded({ extended: false }));
const transporter = nodemailer.createTransport({
service: "hotmail",
auth: {
user: ,
pass: ,
}
});
transporter.verify(function (error, success) {
if (error) {
console.log(error);
} else {
console.log("Server is ready to take our messages");
}
});
app.post('/send', (req, res, next) => {
var name = req.body.name
var email = req.body.email
var subject = req.body.subject
var message = req.body.message
var mail = {
from: name,
to: ,
subject: subject,
text: message
}
transporter.sendMail(mail, (err, data) => {
if (err) {
res.json({
status: 'fail'
})
} else {
res.json({
status: 'success'
})
}
})
})
Frontend
import axios from "axios";
import React from 'react';
class ContactForm extends React.Component {
constructor(props) {
super(props);
this.state = {
name: '',
email: '',
subject: '',
message: ''
}
}
onNameChange(event) {
this.setState({ name: event.target.value })
}
onEmailChange(event) {
this.setState({ email: event.target.value })
}
onSubjectChange(event) {
this.setState({ subject: event.target.value })
}
onMsgChange(event) {
this.setState({ message: event.target.value })
}
submitEmail(e) {
e.preventDefault();
axios({
method: "POST",
url: "/send",
data: this.state
}).then((response) => {
if (response.data.status === 'success') {
alert("Message Sent.");
this.resetForm()
} else if (response.data.status === 'fail') {
alert("Message failed to send.")
}
})
}
resetForm() {
this.setState({ name: '', email: '', subject: '', message: '' })
}
render() {
return (
<div className="section">
<div className="container">
<div className="row">
<div className="col-md-12">
<div className="section-title">
<h2 className="title">Contact Us</h2>
<p>Let us know what you think! In order to provide better service,
please do not hesitate to give us your feedback. Thank you.</p><hr />
<form id="contact-form" onSubmit={this.submitEmail.bind(this)}
method="POST">
<div className="form-group">
<div className="row">
<div className="col-md-6">
<input placeholder="Name" id="name" type="text"
className="form-control" required value={this.state.name}
onChange={this.onNameChange.bind(this)} />
</div>
<div className="col-md-6">
<input placeholder="Email" id="email" type="email"
className="form-control" aria-describedby="emailHelp"
required value={this.state.email} onChange=
{this.onEmailChange.bind(this)} />
</div>
</div>
</div>
<div className="form-group">
<input placeholder="Subject" id="subject" type="text"
className="form-control" required value={this.state.subject}
onChange={this.onSubjectChange.bind(this)} />
</div>
<div className="form-group">
<textarea placeholder="Message" id="message"
className="form-control" rows="1"
required value={this.state.message}
onChange={this.onMsgChange.bind(this)} />
</div>
<button type="submit" className="primary-btn submit">Submit</button>
</form>
</div>
</div>
</div>
</div>
</div>
);
}
}
export default ContactForm;

React, functional component. Input focus is thrown off when a character is entered

I'm new in react. The problem is this - when I enter data into the input, my focus is reset. I understand that it happens due to changeHandler. But I don't understand how to change it. I've seen similar problems, but they are all related to class components. I would like to implement the solution exactly in a functional component, not using classes.
import React, { useContext, useEffect, useState } from 'react'
import { AuthContext } from '../context/AuthContext'
import axios from 'axios';
import { render } from '#testing-library/react';
export const AuthPage = () => {
const auth = useContext(AuthContext)
const [typeOfForm, setTypeOfForm] = useState('login')
const [form, setForm] = useState({
email: '', password: ''
})
const loginHandler = async () => {
try {
var config = {
headers: { 'Access-Control-Allow-Origin': '*' }
};
axios.post('http://localhost:5000/api/login', { ...form }, { headers: { 'Authorization': `Bearer ${auth.token}` } })
.then(response => response.data.map(part => { auth.login(part.token, part.userId); console.log(part) }))
.catch(function (error) {
console.log(error);
});
} catch (e) { }
}
const registerHandler = async () => {
try {
var config = {
headers: { 'Authorization': `Bearer ${auth.token}` }
};
axios.post('http://localhost:5000/api/register', { ...form })
.then(response => response.data.map(part => { auth.login(part.token, part.userId); console.log(part) }))
.catch(function (error) {
console.log(error);
});
} catch (e) { }
}
const changeHandler = event => {
setForm({ ...form, [event.target.name]: event.target.value })
}
return (
<div className="App" key="editor2">
<div className="logreg-bg"></div>
<a href="/">
<h1 id="logreg-logo">Animal Assistance <br /> <span id="logreg-logo-down">save nature togehter</span></h1>
</a>
{typeOfForm == 'login' ? <LoginForm /> : <RegisterForm />}
<h1 id="logreg-logo2"> Created by: <br /> <span id="logreg-logo-down2">PTN</span></h1>
</div>
);
function LoginForm() {
return (
<div id="logreg-form-container">
<h1 id="form-header">Log in</h1>
<div id="label-logreg-input">
<div className="logreg-labels">
<label htmlFor="email" id="login-label">Email</label>
</div>
<input
placeholder="Email"
type="text"
id="login"
name="email"
value={form.email}
onChange={changeHandler}
required />
</div>
<div id="label-logreg-input">
<div className="logreg-labels">
<label htmlFor="password" id="password-label">Password</label>
</div>
<input
placeholder="Password"
type="password"
id="password"
name="password"
value={form.password}
onChange={changeHandler}
required />
<div id="logreg-button-container">
<button
onClick={registerHandler}
id="logreg-form-button"
>Login</button>
</div>
</div>
<div id="go-to-else-container">
<a id="go-to-else"
onClick={() => setTypeOfForm('register')}>Register</a>
</div>
</div>
)
}
function RegisterForm() {
return (
<div id="logreg-form-container">
<h1 id="form-header">Register</h1>
<div id="label-logreg-input">
<div className="logreg-labels">
<label htmlFor="email" id="login-label">Email</label>
</div>
<input
placeholder="Введите email"
value={form.email}
onChange={changeHandler}
type="text"
id="login"
name="email"
required />
</div>
<div id="label-logreg-input">
<div className="logreg-labels">
<label htmlFor="password" id="password-label">Password</label>
</div>
<input
placeholder="Введите пароль"
value={form.password}
onChange={changeHandler}
type="password"
id="password"
name="password"
required />
<div id="logreg-button-container">
<button
type="submit"
id="logreg-form-button"
>Register</button>
</div>
</div>
<div id="go-to-else-container">
<a id="go-to-else"
onClick={() => setTypeOfForm('login')}>Login</a>
</div>
</div>
)
}
}
export default AuthPage;
Problems:
Focus is being lost because currently, input changes the state of a higher level component. The automatically causes a re-rendering of its child (the login or sign up form), because it is being completely defined again.
This causes an automatic re-render since React and browser think it
got a COMPLETELY NEW component.
Solutions:
Move the form state, and changeHandler function, to each respective form component, and allow them to manage their state independently. That way, this won't happen.
Recommended Approach:
If you want to form and changleHandler in a higher level component, then define the child components (Login and Sign Up) separately from AuthPage. Then just pass them the form state, and changeHandler function, as props.
Below if the 2nd approach being implemented
Since you would define both components separately, ensure you pass all the variables and functions in AuthPage, that are needed in each form, as props/parameters too. This is for functional purposes, and because it is best practice for maintenance on react apps.
Let me know if it helps :)
import React, { useContext, useEffect, useState } from 'react'
import { AuthContext } from '../context/AuthContext'
import axios from 'axios';
import { render } from '#testing-library/react';
function LoginForm({form, changeFormType, changeHandler, registerHandler}) {
return (
<div id="logreg-form-container">
<h1 id="form-header">Log in</h1>
<div id="label-logreg-input">
<div className="logreg-labels">
<label htmlFor="email" id="login-label">Email</label>
</div>
<input
placeholder="Email"
type="text"
id="login"
name="email"
value={form.email}
onChange={changeHandler}
required />
</div>
<div id="label-logreg-input">
<div className="logreg-labels">
<label htmlFor="password" id="password-label">Password</label>
</div>
<input
placeholder="Password"
type="password"
id="password"
name="password"
value={form.password}
onChange={changeHandler}
required />
<div id="logreg-button-container">
<button
onClick={registerHandler}
id="logreg-form-button"
>Login</button>
</div>
</div>
<div id="go-to-else-container">
<a id="go-to-else"
onClick={changeFormType}>Register</a>
</div>
</div>
)
}
function RegisterForm({form, changeFormType, changeHandler}) {
return (
<div id="logreg-form-container">
<h1 id="form-header">Register</h1>
<div id="label-logreg-input">
<div className="logreg-labels">
<label htmlFor="email" id="login-label">Email</label>
</div>
<input
placeholder="Введите email"
value={form.email}
onChange={changeHandler}
type="text"
id="login"
name="email"
required />
</div>
<div id="label-logreg-input">
<div className="logreg-labels">
<label htmlFor="password" id="password-label">Password</label>
</div>
<input
placeholder="Введите пароль"
value={form.password}
onChange={changeHandler}
type="password"
id="password"
name="password"
required />
<div id="logreg-button-container">
<button
type="submit"
id="logreg-form-button"
>Register</button>
</div>
</div>
<div id="go-to-else-container">
<a id="go-to-else"
onClick={changeFormType}>Login</a>
</div>
</div>
)
}
const AuthPage = () => {
const auth = useContext(AuthContext)
const [typeOfForm, setTypeOfForm] = useState('login')
const [form, setForm] = useState({
email: '', password: ''
})
const loginHandler = async () => {
try {
var config = {
headers: { 'Access-Control-Allow-Origin': '*' }
};
axios.post('http://localhost:5000/api/login', { ...form }, { headers: { 'Authorization': `Bearer ${auth.token}` } })
.then(response => response.data.map(part => { auth.login(part.token, part.userId); console.log(part) }))
.catch(function (error) {
console.log(error);
});
} catch (e) { }
}
const registerHandler = async () => {
try {
var config = {
headers: { 'Authorization': `Bearer ${auth.token}` }
};
axios.post('http://localhost:5000/api/register', { ...form })
.then(response => response.data.map(part => { auth.login(part.token, part.userId); console.log(part) }))
.catch(function (error) {
console.log(error);
});
} catch (e) { }
}
const changeHandler = event => {
setForm({ ...form, [event.target.name]: event.target.value })
}
const changeFormType = event =>{
//add your condition based of e.target
setTypeOfForm('login')
//add your condition based of e.target
setTypeOfForm('register')
}
return (
<div className="App" key="editor2">
<div className="logreg-bg"></div>
<a href="/">
<h1 id="logreg-logo">Animal Assistance <br /> <span id="logreg-logo-down">save nature togehter</span></h1>
</a>
{typeOfForm == 'login' ? <LoginForm
changeHandler={changeHandler}
form={form}
changeFormType={changeFormType}
registerHandler={registerHandler}/>
: <RegisterForm
changeHandler={changeHandler}
form={form}
changeFormType={changeFormType}
/>}
<h1 id="logreg-logo2"> Created by: <br /> <span id="logreg-logo-down2">PTN</span></h1>
</div>
);
}
export default AuthPage;

React form submit triggers two times

I have React login form. The problem is form submit is called two times. I dont understand it. Can somebody tell me please why? Thanks a lot.
import React from "react"
import LoginErrors from "./LoginErrors"
import LoginSuccess from "./LoginSuccess"
import axios from 'axios'
import { withRouter } from "react-router-dom";
class Login extends React.Component
{
constructor(props)
{
super(props)
this.state = {
name: '',
password: '',
errors: [],
success: []
}
}
changeName = e =>
{
this.setState({name: e.target.value});
}
changePassword = e =>
{
this.setState({password: e.target.value});
}
sendData(e)
{
e.preventDefault();
this.setState({'errors': [], 'success': []});
let formData = new FormData();
formData.set('name', this.state.name);
formData.set('password', this.state.password);
axios({
method: 'POST',
url: 'http://localhost:8000/login',
data: formData,
headers: {
'Content-Type': 'text/html',
'X-Requested-With': 'XMLHttpRequest',
}
})
.then(response => {
// ? returns undefined if variable is undefined
if( response.data?.errors?.length )
{
this.setState({errors: response.data.errors})
}
if( response.data?.success?.length )
{
let data = response.data
this.props.setAccessToken(data.token)
this.props.setUserName(data.user.name)
this.props.history.push('/')
}
})
.catch(response => {
this.setState({errors: ['Login fails. Try it again later please.']})
});
}
render() {
return (
<div className="row justify-content-md-center">
<div className="col-sm-12 col-md-6">
<div id="loginForm">
<h2 className="">Login</h2>
<LoginSuccess success={this.state.success} />
<LoginErrors errors={this.state.errors} sendParentMessage={this.handleErrorsChildMessage} />
<form onSubmit={e => {this.sendData(e)}}>
<div className="form-group">
<label htmlFor="name">Name</label>
<input ref={this.email} name="name" className="form-control" type="text" onChange={this.changeName} />
</div>
<div className="form-group">
<label htmlFor="password">Heslo</label>
<input ref={this.password} name="password" className="form-control" type="password" onChange={this.changePassword} />
</div>
<div className="form-group">
<button name="sbmt" className="btn btn-primary" type="submit">Odoslať</button>
</div>
</form>
</div>
</div>
</div>
);
}
}
So the problem is in axios preflyght request which is related to the CORS policy. But How to stop it?

authentication log in form with jwt and react

I have made and fetched a Login form with JWT and react. I managed to fetched the data for the username and password and everything works perfectly but then I want to redirect the user to a new page when he clicks on submit and I have no idea how to do that. I'm also using react router. Any help will be welcome
import React, { Component } from "react";
import axios from "axios";
export default class Login extends Component {
constructor(props) {
super(props);
this.state = {
username: "test",
password: "test",
}
}
handleChange = (e) => {
this.setState({
[e.target.name]: e.target.value,
})
}
login = () => {
const {username, password} = this.state;
axios(`/users/login`, {
method: "POST",
data: {
username,
password,
}
})
.then(response => {
localStorage.setItem('token', response.data.token);
console.log(response);
})
.catch(error => {
console.log(error)
})
}
render() {
return (
<div className="log">
<h3>Sign In</h3>
<div className="form-group">
<label>Username</label>
<input type="username" className="form-control" placeholder="Enter username" name="username" value={this.state.username} onChange={this.handleChange} />
</div>
<div className="form-group">
<label>Password</label>
<input type="password" className="form-control" placeholder="Enter password" name="password" value={this.state.password} onChange={this.handleChange} />
</div>
<div className="form-group">
<div className="custom-control custom-checkbox">
<input type="checkbox" className="custom-control-input" id="customCheck1" />
<label className="custom-control-label" htmlFor="customCheck1">Remember me</label>
</div>
</div>
<button type="submit" className="btn btn-primary btn-block" onClick={this.login}>Submit</button>
<p className="forgot-password text-right">
Forgot password?
</p>
</div>
);
}
}
import withRouter import {withRouter} from 'react-router-dom';
remove export before class Login class Login extends Component {...
export class at the end of the file: export default withRouter(Login);
and use react-router-dom:
axios(`/users/login`, {
//...
})
.then(response => {
localStorage.setItem('token', response.data.token);
console.log(response);
this.props.history.push('/url');
})
//...

React props.auth.user is undifined when registering a user

In my project when I try to print the name of the user that just registered it shows undifined.
When I register a user he is redirected to the dashboard page where is name should apear but it doesn´t. But when I reload the page the name shows correctly.
The login is done similiar to register but works fine.
My component to register bidder.
import React, { Component } from "react";
import { Link, Redirect } from "react-router-dom";
import { connect } from "react-redux";
import PropTypes from "prop-types";
import { registerBidder } from "../../actions/auth";
import { createMessage } from "../../actions/messages";
export class RegisterBidder extends Component {
state = {
email: "",
password: "",
password2: "",
first_name: "",
last_name: "",
aluno: "false"
};
static propTypes = {
registerBidder: PropTypes.func.isRequired,
isAuthenticated: PropTypes.bool
};
onSubmit = e => {
e.preventDefault();
const {
email,
password,
password2,
first_name,
last_name,
aluno
} = this.state;
if (password != password2) {
this.props.createMessage({
passwordNotMatch: "Passwords não são iguais"
});
} else {
const newUser = {
email,
first_name,
last_name,
password,
aluno
};
this.props.registerBidder(newUser);
}
};
handleChange = () => {
if (this.state.aluno == "false") {
this.setState({ aluno: "true" });
} else {
this.setState({ aluno: "false" });
}
};
onChange = e => this.setState({ [e.target.name]: e.target.value });
render() {
if (this.props.isAuthenticated && this.registerBidder) {
return <Redirect to="/dashboardBidder" />;
}
const { email, password, password2, first_name, last_name } = this.state;
return (
<div className="col-md-6 m-auto">
<div className="card card-body mt-5">
<h2 className="text-center">Register</h2>
<form onSubmit={this.onSubmit}>
<div className="form-group">
<label>Email</label>
<input
type="email"
className="form-control"
name="email"
onChange={this.onChange}
value={email}
/>
</div>
<div className="form-group">
<label>First Name</label>
<input
type="name"
className="form-control"
name="first_name"
onChange={this.onChange}
value={first_name}
/>
</div>
<div className="form-group">
<label>Last Name</label>
<input
type="name"
className="form-control"
name="last_name"
onChange={this.onChange}
value={last_name}
/>
</div>
<div className="form-group">
<label>Password</label>
<input
type="password"
className="form-control"
name="password"
onChange={this.onChange}
value={password}
/>
</div>
<div className="form-group">
<label>Confirm Password</label>
<input
type="password"
className="form-control"
name="password2"
onChange={this.onChange}
value={password2}
/>
</div>
<div className="react__checkbox">
<label>Aluno</label>
<input
type="checkbox"
className="react__checkbox--input"
aluno={this.state.aluno}
onChange={this.handleChange}
/>
</div>
<div className="form-group">
<button type="submit" className="btn btn-primary">
Register
</button>
</div>
<p>
Already have an account? <Link to="/login">Login</Link>
</p>
</form>
</div>
</div>
);
}
}
const mapStateToProps = state => ({
isAuthenticated: state.auth.isAuthenticated
});
export default connect(mapStateToProps, { registerBidder, createMessage })(RegisterBidder);
My action to register.
export const registerBidder = ({
email,
first_name,
last_name,
password,
aluno
}) => dispatch => {
// Headers
const config = {
headers: {
"Content-Type": "application/json"
}
};
// Request Body
const body = JSON.stringify({
user: { email, first_name, last_name, password },
aluno: aluno
});
console.log(body);
dispatch({ type: USER_LOADING });
axios
.post("/api/auth/registar/bidder", body, config)
.then(res => {
dispatch({
type: REGISTER_SUCCESS,
payload: res.data
});
})
.catch(err => {
dispatch(returnErrors(err.response.data, err.response.status));
dispatch({
type: REGISTER_FAIL
});
});
};

Resources