React: Error-Message does not show up, while others do? - html

I have this simple Login-Form, in which I want to display an Error-Message, which contains Login tries (3 tries possible). Somehow, my one errormessage (loginTries) is not being displayed. Why?
My form is running the method handleSubmitAndStartTimer() when I submit it. You can find more comments and details below:
export const Login = () => {
const [errorMessages, setErrorMessages] = useState({});
const [loginFailCounter, setLoginFailCounter] = useState(2);
const [firstTimeSubmitted, setFirstTimeSubmitted] = useState(false);
const mockUserData = [
{
username: "user1",
password: "pass1",
istGesperrt: false,
},
];
const handleSubmitAndStartTimer = (event) => {
setFirstTimeSubmitted(true);
event.preventDefault();
var { benutzername, passwort } = document.forms[0];
const userData = mockUserDaten.find(
(user) => user.username === benutzername.value
);
// Compare user info
if (userData) {
if (!userData.istGesperrt) {
if (userData.password !== passwort.value) {
setLoginFailCounter(loginFailCounter - 1);
// THIS DOESNT WORK!
setErrorMessages({ name: "loginTries", message: errors.loginTries, });
// ALL THESE ERROR MESSAGES WORK!
// Invalid password
setErrorMessages({ name: "passwort", message: errors.passwort });
} else {
// Username not found
setErrorMessages({
name: "benutzername",
message: errors.benutzername,
});
}
} else {
setErrorMessages({
name: "userGesperrt",
message: errors.userGesperrt,
});
}
}
};
// This method is called to display to correct message
const renderErrorMessage = (name) =>
name === errorMessages.name && (
<div className="error">{errorMessages.message}</div>
);
const errors = {
benutzername: "invalid username",
passwort: "invalid password",
loginTries: loginFailCounter + " Tries possible!",
userGesperrt: "",
};
const renderForm = (
<div className="form">
<form onSubmit={handleSubmitAndStartTimer}>
<div className="input-container">
<label for="benutzername">Benutzername</label>
<input type="text" id="benutzername" name="benutzername" required />
{renderErrorMessage("benutzername")}
</div>
<div className="input-container">
<label for="passwort">Passwort</label>
<input type="passwort" id="passwort" name="passwort" required />
{renderErrorMessage("passwort")}
</div>
<div className="button-container">
<input type="submit" value="Log in" />
</div>
{renderErrorMessage("userGesperrt")}
// THIS MESSAGE ISNT BEING SHOWN!
{renderErrorMessage("loginTries")}
</form>
</div>
);
return (
<div className="app">
<div className="login-form">
<div className="title">Sign In</div>
{isSubmitted ? <div>User is successfully logged in</div> : renderForm}
</div>
</div>
);
};
export default Login;

Related

Can I put HTML code in string value which I send Google Firebase Cloud Database in React?

I am using React. I am sending and pulling string data from Google Firebase Cloud Database. I want to put HTML code in my string value and I want the browser to implement it.
For example; I sent a string data like this:
lorem ipsum dolor <br> sit amet <ul><li>item1</li><li><item2></li><ul>
And I pulled like this
<div>{data.description}</div>
The result is a string in p tag:
lorem ipsum dolor <br> sit amet <ul><li>item1</li><item2><ul>
But I want to browser implement html codes in string data. Like this
lorem ipsum dolor sit amet item1item2
Can I do that?
If it is neccesary this is my sending code in React
function Lessons({ language }) {
const [lesson, setLesson] = useState({
id: "",
topic: "",
head: "",
description: "",
image: "",
});
const [disabled, setDisabled] = useState(true);
const [progres, setProgres] = useState(0);
const [imageUrl, setImageUrl] = useState("");
function handleChange(e) {
lesson[e.target.id] = e.target.value;
setLesson({ ...lesson, lesson });
if (
lesson.id !== "" &&
imageUrl !== "" &&
lesson.description !== "" &&
lesson.head !== ""
) {
setDisabled(false);
} else {
setDisabled(true);
}
}
const imageHandler = (e) => {
e.preventDefault();
const image = e.target[0].files[0];
uploadImages(image);
};
const uploadImages = (image) => {
const storageRefLes = ref(storage, `/lesAndEx/${image.name}`);
const uploadTask = uploadBytesResumable(storageRefLes, image);
uploadTask.on(
"state_changed",
(snapshot) => {
const prog = Math.round(
(snapshot.bytesTransferred / snapshot.totalBytes) * 100
);
setProgres(prog);
},
(err) => console.log(err),
() => {
getDownloadURL(uploadTask.snapshot.ref).then((url) =>
setImageUrl(url, imageUrl)
);
}
);
};
const add = async (event) => {
event.preventDefault();
const newTopic = lesson.topic;
switch (language) {
case "English":
await setDoc(doc(db, "lessons-data-" + newTopic, lesson.id), {
head: lesson.head,
image: imageUrl,
description: lesson.description,
});
break;
case "Dutch":
await setDoc(doc(db, "lessons-data-Dutch-" + newTopic, lesson.id), {
head: lesson.head,
image: imageUrl,
description: lesson.description,
});
break;
case "Turkish":
await setDoc(doc(db, "lessons-data-Turkish-" + newTopic, lesson.id), {
head: lesson.head,
image: imageUrl,
description: lesson.description,
});
break;
}
setLesson({
id: "",
topic: "",
head: "",
image: "",
description: "",
});
setImageUrl("");
setDisabled(true);
setProgres(0);
};
return (
<div className="bigContainer">
<h1>Lessons</h1>
<h2>Language: {language}</h2>
<div>
<div className="topicImageLoader">
<form onSubmit={imageHandler}>
<input type="file"></input>
<button type="submit">Upload</button>
</form>
<h2>Uploaded {progres} %</h2>
</div>
<div className="topAndExLabels">
<div>
<label for="id">
Lesson Id
<input
required
type="text"
id="id"
value={lesson.id}
onChange={handleChange}
placeholder="Id"
></input>
</label>
</div>
<div>
<label for="topic">
Lesson Topic
<input
required
type="text"
id="topic"
value={lesson.topic}
onChange={handleChange}
placeholder="Write exactly"
></input>
</label>
<label for="image">
Lesson Image
<input
required
disabled
type="url"
id="image"
value={imageUrl}
onChange={handleChange}
placeholder="imageUrl"
></input>
</label>
</div>
<div>
<label for="head">
Lesson Head
<input
required
type="text"
id="head"
value={lesson.head}
onChange={handleChange}
placeholder="head"
></input>
</label>
<div>
<div className="textAreaArea">Description</div>
<textarea
className="textAreaArea"
required
rows="8"
id="description"
value={lesson.description}
onChange={handleChange}
placeholder="lesson"
></textarea>
</div>
</div>
</div>
<div className="topAddButtonCont">
<button disabled={disabled} onClick={add}>
ekle
</button>
</div>
</div>
</div>
);
}
export default Lessons;
And this is my pulling code
function LessonPage() {
const [lessons, setLessons] = useState([]);
const [current, setCurrent] = useState(0);
const length = lessons.length;
let topicName = useLocation();
const nextSlide = () => {
setCurrent(current === length - 1 ? 0 : current + 1);
};
const prevSlide = () => {
setCurrent(current === 0 ? length - 1 : current - 1);
};
useEffect(() => {
onSnapshot(
collection(db, "lessons-data-" + topicName.state.state),
(snapshot) =>
setLessons(
snapshot.docs.map((doc) => ({
id: doc.id,
data: doc.data(),
}))
)
);
console.log(topicName.state.state);
}, []);
return (
<div className="slideBody">
<div className="mainSlide">
<FaArrowAltCircleLeft className="left-arrow" onClick={prevSlide} />
<FaArrowAltCircleRight className="right-arrow" onClick={nextSlide} />
{lessons.map(({ id, data }, index) => (
<div className={index === current ? "data active" : "data"} key={id}>
{index === current && (
<div className="slide">
<div className="dataHeadLesson">{data.head}</div>
<div className="dataImageLesson">
<img src={data.image}></img>
</div>
<div className="dataDesc">{data.description}</div>
</div>
)}
</div>
))}
</div>
</div>
);
}
export default LessonPage;
If I understand your querstion correctly you are receiving an html that you want to display using react JSX
take a look at this https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml
Thx to Ilias Aboubeker. I fix the code like this and it works!
<div className="dataDesc" dangerouslySetInnerHTML={{ __html: data.description }}></div>

Netflify Serverless Function JSON parse error Sendgrid API

My contact form is not sending the frontend user to my thank you page neither is it sending any information to me via the Sendgrid APi. The issue comes from the fact that I'm not sure how to turn the JSON object into a string and then straight back to an Object..... Or as you can see I have a hard time even framing my question. The goal would be to send the information to my email account using Sendgrid API.
The form is live here:
https://www.metsanotus.fi/yhteydenotto
The code is based 99% off these two tutorials:
https://oliverschmidt.dev/blog/adding-a-contact-form-to-a-static-site-with-netlify-functions/
https://dev.to/char_bone/using-netlify-lambda-functions-to-send-emails-from-a-gatsbyjs-site-3pnb
The code for the contact-page:
https://gist.github.com/otsolap/f05cd4e3a1a08794f61a6d5730abc695
import React, { useState } from "react";
import { graphql } from "gatsby"
import { RiSendPlane2Line } from "react-icons/ri";
import Layout from "../components/layout"
import SEO from "../components/seo"
export const pageQuery = graphql`
query ContactQuery($id: String!){
markdownRemark(id: { eq: $id }) {
id
html
excerpt(pruneLength: 140)
frontmatter {
title
}
}
site {
siteMetadata {
title
}
}
}
`
const Contact = ({ data }) => {
const { markdownRemark, site } = data // data.markdownRemark holds your post data
const { frontmatter, html } = markdownRemark
// input type hidden on netlifytä varten, jotta netlify tietää mikä lomake kyseessä.
// contact on meidän lomake, niin kaikki viestit löytyy contact-lomakkeen alta.
// honeypot=bot-field on botteja varten.
// p hidden pitää kohdan piilossa, mutta console.logilla sen löytää. ;-)
const [formState, setFormState] = useState({
name: '',
email: '',
phone: '',
subject: '',
message: '',
})
const handleChange = (e) => {
setFormState({
...formState,
[e.target.name]: e.target.value,
});
}
const handleSendEmail = async (event) => {
event.preventDefault();
try {
const response = await fetch("/.netlify/functions/contact-form-email", {
method: "POST",
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(formState),
})
if (!response.ok) {
//EI 200 response
return
}
//all OK
} catch (event) {
//error
}
}
return (
<Layout className="contact-page">
<SEO
title={frontmatter.title}
description={frontmatter.title + " " + site.siteMetadata.title}
/>
<div className="wrapper">
<h1>{frontmatter.title}</h1>
<div className="description" dangerouslySetInnerHTML={{ __html: html }} />
<form className="contact-form"
action="/kiitos"
name="contact"
method="POST"
data-netlify="true"
value="contact"
data-netlify-honeypot="bot-field"
onSubmit={handleSendEmail}
>
<input type="hidden" name="form-name" value="contact" />
<p hidden><input name="bot-field" /></p>
<p>
<label><input
required
placeholder="Nimi *"
type="text"
name="name"
onChange={handleChange}
/>
</label>
</p>
<p>
<label><input required
placeholder="Sähköposti *"
type="email"
name="email"
onChange={handleChange}
/>
</label>
</p>
<p>
<label><input required
placeholder="Puhelin *"
type="number"
name="phone"
onChange={handleChange}
/>
</label>
</p>
<p>
<label><input placeholder="Aihe"
type="text"
name="subject"
onChange={handleChange}
/>
</label>
</p>
<p>
<label><textarea
placeholder="Viesti"
name="message"
onChange={handleChange}
></textarea></label>
</p>
<p className="text-align-center">
<button className="button"
type="submit">
Lähetä<span className="icon -right"><RiSendPlane2Line />
</span>
</button>
</p>
</form>
</div>
</Layout>
)
}
export default Contact
The code for the serverless function:
https://gist.github.com/otsolap/e157b136aee040281f20ba87131014eb
require('dotenv').config();
const sgMail = require('#sendgrid/mail')
const {
SENDGRID_API_KEY,
METSAN_OTUS_NAME,
METSAN_OTUS_ADDRESS }
= process.env
sgMail.setApiKey(SENDGRID_API_KEY)
exports.handler = async (event, context, callback) => {
const payload = JSON.parse(event.body)
const { email, subject, message } = payload
const msg = {
to: METSAN_OTUS_ADDRESS,
name: METSAN_OTUS_NAME,
from: email,
subject: subject ? subject : 'Yhteydenotto lomakkeesta',
text: message,
};
try {
await sgMail.send(msg)
return {
statusCode: 200,
body: "Viesti lähetetty"
}
} catch (e) {
return {
body: e.message,
statusCode: 500,
}
}
};
When I keep the JSON.parse(body.event) this is the error it displays:
https://gist.github.com/otsolap/79830f6cf1e9b247c63c1f3f49c5286b
SyntaxError: Unexpected token u in JSON at position 0
If I change the line 13 of serverless-function.js from JSON.parse(event.body) to (for example) JSON.stringify(event.body) the error becomes this:
TypeError: Cannot destructure property 'email' of 'payload' as it is undefined.
So I guess my question is how should I formulate my serverless function so that the React object from UseState can become readable for my function?

Is there anyway to authenticate the user type(user and Supplier) without any token in react and go with different page when I fetch the response api?

is it anyway or solution that can authenticate the result in response JSON without any token authentication? My project have two type of user (user=1 and supplier=2). I need both of this user has different pages when they login to my system. The response JSON are as below:
This user is normal user will go to user page, while other user with user type of 2 will go to supplier page.
Here is my code:
login(){
if(this.state.loginEmail && this.state.loginPassword){
PostData('api/users/login', this.state).then ((result) => {
let responseJSON = result;
console.log(responseJSON)
if(responseJSON.user){
sessionStorage.setItem('user', responseJSON);
// console.log("Home Page")
this.setState({redirect: true});
}else{
console.log("Login Error")
alert("wrong user credential")
}
});
}
}
On the render component, when user login successfully I use redirect to go to Home page"/home":
render(){
if(this.state.redirect){
return (<Redirect to={{
pathname: '/home',
state: { loginEmail : this.state.loginEmail }}}/>)
}
if(sessionStorage.getItem("user")){
return (<Redirect to ={'/home'}/>)
}
return (
<div className="login-background">
<div className = " login-form">
<h1>Login</h1>
<div className = "txtb">
<input type="text" name="loginEmail" placeholder= "email" onChange={this.onChange}/>
</div>
<div className = "txtb">
<input type="password" name="loginPassword" placeholder="password" onChange={this.onChange}/>
</div>
<input type="submit" value="Login" className="logbtn" onClick={this.login}/>
<div className = "bottom-text">
Dont have account? Sign up
</div>
</div>
</div>
);
}
What I want is when userType is equal to 2, they will go to supplier page "/supplier".
Assuming that you have already connected your component with react-router, this is how you can redirect your user to the respective paths based on the userType.
login(){
if(this.state.loginEmail && this.state.loginPassword){
PostData('api/users/login', this.state).then ((result) => {
const { data: { user_info: { userType } } } = result;
if (userType === 1) {
history.push('/home');
} else if (userType === 2) {
history.push('/supplier')
}
});
}
}

How do i send data from 2 inputs into one json server object?

I am trying to create a simple login sistem using react and json server (on localhost port).
I have 2 inputs, one for name the other for password.
My problem is that when i try to submit those inputs, on the server side both name and password appear with the values from the password.
class AddAcc extends Component {
constructor(props) {
super(props);
this.input = null;
this.pushAcc = this.pushAcc.bind(this)
}
async pushAcc() {
try {
await Axios
.post(
`${BASE_URL}users`,
{
name: this.input.value,
password: this.input.value,
},
{
'Content-Type': 'aplication/json'
}
)
this.props.newAcc(this.input.value);
} catch(e) {
}
}
render() {
return(
<div>
<p>
<input
ref={name => this.input = name} />
</p>
<div>
<h3>Enter Password</h3>
</div>
<p>
<input
ref={pass => this.input = pass} />
</p>
<button onClick = {this.pushAcc} type="submit"> SUBMIT </button>
</div>
)
}
}
export default AddAcc;
Because you are using same ref this.input for both name and password.
Change for password
<input ref={pass => this.passwordInput = pass} />
This is simply because you are using same name for name ans pass. So simple solution is this,
<input ref={name => this.inputName = name} />
<input ref={pass => this.inputPass = pass} />
Then do this,
await Axios
.post(
`${BASE_URL}users`,
{
name: this.inputName.value,
password: this.inputPass.value,
},
{
'Content-Type': 'aplication/json'
}
)

Angular 6 error doesn't fire

I am learning angular and for my example using Firebase createUserWithEmailAndPassword for sign-up. This returns a promise which i have changed to observable using from.
In firebase minimum password length is 6 characters. When i provide 5 characters, in the console i see the error message but in my sign-up event, success message shows rather than error. What am i missing here?
AuthService
import * as firebase from 'firebase';
import { throwError, from } from 'rxjs';
export class AuthService{
//user sign up, its a promise so listen for errors and log
signUpUser(email: string, password: string){
//return an observable using from
return from(
firebase.auth().createUserWithEmailAndPassword(email, password)
.then(
(authData) => {
//good
console.log("User created successfully with payload-", authData);
return authData;
}
)
.catch(
(error) => {
//error
console.log(error);
return throwError(error);;
}
)
);
}
}
Sign-up component
onSignup(form: NgForm){
const email = form.value.email;
const password = form.value.password;
this.authService.signUpUser(email, password).subscribe(
(authData) => {
alert("Signup successful");
this.router.navigate(['/sign-in']);
},
(error) => {
alert(error.message);
}
);
}
Also i am using then in the authService method. How can i do .pipe(map(return authData.json()))?
Update 1:
Following helped and i am getting my error, on successful registration i am getting redirected to the sign-in view.
Convert promise to observable
AuthService
import { from } from 'rxjs';
signUpUserNew(email: string, password: string){
var subscription = from(firebase.auth().createUserWithEmailAndPassword(email, password));
return subscription;
}
Sign-up Component
//property to hold result of sign-up error
error = '';
onSignup(form: NgForm){
const email = form.value.email;
const password = form.value.password;
//this.authService.signUpUser(email, password);
this.authService.signUpUserNew(email, password)
.subscribe(
(firebaseUser) => {
console.log(firebaseUser);
this.router.navigate(['/sign-in']);
},
(error) => {
this.error = error.message;
}
);
}
View
<h2>Register</h2>
<div class="row">
<div class="col-xs-12 col-sm-10 col-md-8 col-sm-offset-1 col-md-offset-2">
<form (ngSubmit)="onSignup(f)" #f="ngForm">
<div class="form-group">
<label for="email">Email</label>
<input type="email" id="email" name="email" ngModel class="form-control" #email="ngModel" required email>
<span class="help-block" *ngIf="!email.valid && email.touched">Please enter a valid email!</span>
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" id="password" name="password" ngModel class="form-control" #password="ngModel" required minlength="6">
<span class="help-block" *ngIf="!password.valid && password.touched && !password.errors?.minlength">Please enter a valid password!</span>
<span class="help-block" *ngIf="!password.valid && password.touched && password.errors?.minlength">Password must be at least 6 characters long</span>
</div>
<p class="error" *ngIf="error">{{ error }}</p>
<button class="btn btn-primary" type="submit" [disabled]="!f.valid">Sign Up</button>
</form>
</div>
</div>
Result
Pending
Now i still need help implementing pipe and map operators.
I am getting the following error on .json:
[ts] Property 'json' does not exists on type 'UserCredential'
onSignup(form: NgForm){
const email = form.value.email;
const password = form.value.password;
//this.authService.signUpUser(email, password);
this.authService.signUpUserNew(email, password)
.pipe(
map(
(firebaseUser) => {
return firebaseUser.json();
}
)
)
.subscribe(
(firebaseUser) => {
console.log(firebaseUser);
this.router.navigate(['/sign-in']);
},
(error) => {
this.error = error.message;
}
);
}
Firstly, I guess you should call fromPromise instead of from, so try the following:
import 'rxjs/add/observable/fromPromise';
import { Observable } from "rxjs/Observable";
signUpUser(email: string, password: string){
//return an observable using fromPromise
const obs$ = fromPromise(
firebase.auth().createUserWithEmailAndPassword(email, password)
);
// you can call .pipe() here, and it will return an observable
return obs$.pipe(
map(x => console.log('PUT YOUR MAP FUNCTION HERE.')),
filter(x => console.log('Call filter() if you want'))
);
}
And you can subscribe to this observable
const subscription = this.authService.signUpUser(email, password).subscribe(
(firebaseUser) => {
console.log('firebase user: ', firebaseUser);
alert("Signup successful");
this.router.navigate(['/sign-in']);
},
(error) => {
alert(error.message);
}
);