this.props.history.push('/') IS NOT WORKING in CLASS Component - javascript

Please help me to resolve the issue of this.props.history.push('/') IS NOT WORKING in CLASS Component. As we do not have any scope of using history anymore. Unable to implement navigate.
Please do help. Same issue with props.location.state.contact.
**const { name, email } = props.location.state.contact;**
import React, { Component } from "react";
import "../assets/css/AddContact.css";
import { Navigate } from "react-router-dom";
import { v4 as uuid } from "uuid";
class AddContact extends Component {
state = {
id: uuid(),
name: "",
email: "",
};
add = (e) => {
e.preventDefault();
if (this.state.name === "" || this.state.email === "") {
alert("All fields are required!");
return;
}
this.props.addContactHandler(this.state);
this.setState({ name: "", email: "" });
this.props.history.push("/");
};
render() {
return (
<div className="contactForm">
<h2 className="contactForm__title">Add Contact</h2>
<div className="contactForm__form">
<form action="/" method="post" onSubmit={this.add}>
<div className="contactForm__nameField">
<label htmlFor="name">Name</label>
<br />
<input
type="text"
placeholder="Enter your name"
name="name"
id="name"
value={this.state.name}
onChange={(e) => this.setState({ name: e.target.value })}
/>
</div>
<div className="contactForm__emailField">
<label htmlFor="email">Email</label>
<br />
<input
type="email"
placeholder="Enter your email"
name="email"
id="email"
value={this.state.email}
onChange={(e) => this.setState({ email: e.target.value })}
/>
</div>
<button className="contactForm__button">Add</button>
</form>
</div>
</div>
);
}
}
export default AddContact;
I tried out from all of my references.

You need to use the withRouter Higher Order Component provided with the React Router library in order to get access to those props (history and location automatically).
So just import that, and change your export to
export default withRouter(AddContact);
[Note that this assumes you are using React Router v5 or before - there is no withRouter in v6 which is the latest version. But your use of a class component implies that you are using an earlier version - v6 only works well if you use function components, as withRouter has been replaced with Hooks.]

Related

How to integrate react-intl-tel-input

Hello I am new in ReactJS and I have to implement react-intl-tel-input for taking phone number from all over the world but while integration I was facing some issues. When I write this code:
<IntlTelInput
containerClassName="intl-tel-input"
inputClassName="form-control"
name="mobile"
placeholder="Enter Your Number"
input
type="tel"
value={this.state.phoneNumber}
onChange={this.handleChange}
I was not able to access this.handleChange but When I write my normal code like this
<input
type="tel"
id="phone"
name="mobile"
placeholder="Enter Your Number"
required
onChange={this.handleChange}
/>
I was able to access this.handleChange and my code work perfectly but I was unable to take country code. If anyone know the solution please help. I was getting this error
TypeError: Cannot read properties of null (reading 'phoneNumber')
This is my complete code.
Login.js
import React from 'react'
import firebase from './firebase'
import 'firebase/auth';
import "./App.css";
import { getDatabase, ref, child, get } from "firebase/database";
import IntlTelInput from 'react-intl-tel-input';
import 'react-intl-tel-input/dist/main.css';
class Login extends React.Component {
handleChange = (e) => {
console.log (e)
const { name, value } = e.target
this.setState({
[name]: value
})
console.log (value)
this.setState({ phoneNumber: value }, () => {
console.log(this.state.phoneNumber);
});
}
configureCaptcha = () =>{
window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier('sign-in-button', {
'size': 'invisible',
'callback': (response) => {
// reCAPTCHA solved, allow signInWithPhoneNumber.
this.onSignInSubmit();
console.log("Recaptca varified")
},
// defaultCountry: "IN"
}
);
}
onSignInSubmit = (e) => {
e.preventDefault()
this.configureCaptcha()
const phoneNumber = this.state.mobile
console.log(phoneNumber)
const appVerifier = window.recaptchaVerifier;
const dbRef = ref(getDatabase());
get(child(dbRef, `Users/${phoneNumber}`)).then((snapshot) => {
if (snapshot.exists()) {
firebase.auth().signInWithPhoneNumber(phoneNumber, appVerifier)
.then((confirmationResult) => {
window.confirmationResult = confirmationResult;
alert('An OTP has been sent to your registered mobile number')
localStorage.setItem("Phone_No", phoneNumber)
console.log(localStorage.getItem('Phone_No'));
}).catch((error) => {
console.error(error);
alert("Oops! Some error occured. Please try again.")
});
}
else {
alert('Sorry, this mobile number is not registered with us. Please use your registered mobile number.');
}
})
}
onSubmitOTP = (e) => {
e.preventDefault()
const code = this.state.otp
console.log(code)
window.confirmationResult.confirm(code).then((result) => {
// User signed in successfully.
const Users = result.user;
console.log(JSON.stringify(Users))
this.props.history.push("/home");
}).catch((error) => {
alert("You have entered wrong code")
});
}
render() {
return (
<div className="Main-header">
<img src="./55k-logo.png" alt="Company Logo" style={{ height: "80px", width: "200px" }} />
<br />
<div>
<h2>Login Form</h2>
<p>Limtless Water. From Unlimited Air.</p>
<form onSubmit={this.onSignInSubmit}>
<div id="sign-in-button"></div>
{/* <PhoneInput */}
<label>Mobile Number</label> <br />
{/* for="phoneNumber" */}
<IntlTelInput
containerClassName="intl-tel-input"
inputClassName="form-control"
name="mobile" placeholder="Enter Your Number"
input type="tel" value={this.state.phoneNumber}
onChange={this.handleChange}
/>
{/* <input type="tel" id="phone" name="mobile" placeholder="Enter Your Number" required onChange={this.handleChange} /> */}
<div className="buttons">
<button type="submit">Submit</button>
</div>
</form>
</div>
<div>
<form onSubmit={this.onSubmitOTP}>
<label >Code</label> <br />
{/* for="code" */}
<input type="number" name="otp" placeholder="Enter The 6 Digit OTP" required onChange={this.handleChange} />
<div className="buttons" >
<button type="submit">Submit</button>
</div>
</form>
</div>
</div>
)
}
}
export default Login;
Issues
There is no defined initial state so this is why accessing this.state.phoneNumber is throwing an error.
The IntlTelInput component takes an onPhoneNumberChange handler that takes a validation status, current value, and country details as arguments instead of an onChange handler taking an onChange event object.
Solution
Provide valid initial state for the component. In React class components state is simply a class property, it just needs to be defined.
state = {};
Create a new change handler specifically for the IntlTelInput component.
handlePhoneChange = (status, phoneNumber, country) => {
this.setState({ phoneNumber });
};
Switch from onChange to onPhoneNumberChange event handler.
<IntlTelInput
containerClassName="intl-tel-input"
inputClassName="form-control"
name="mobile"
placeholder="Enter Your Number"
input
type="tel"
value={this.state.phoneNumber}
onPhoneNumberChange={this.handlePhoneChange}
/>

TypeError: Cannot read property 'email' of undefined while using form with Multiple Inputs

I'm a beginner in React and stuck with some problem.I'm getting an error as "TypeError: Cannot read property 'email' of undefined". Please find the error screenshot below:-
SignIn.js
import React from 'react';
import {useState} from 'react';
export default function SignIn()
{
const{forInp,setForm}=useState({
email:"abc#gmail.com",
password:""
});
function handleChange(event)
{
setForm({
...forInp,
[event.target.name]:event.target.value});
}
function handleSubmit(event)
{
event.preventDefault();
setForm({[event.target.name]:""});
}
return(
<div>
<form onSubmit={handleSubmit}>
<input type="email" name="email" value={forInp.email} placeholder="Email" onChange={handleChange}/>
<input type="Password" name="password" value={forInp.password} placeholder="Password" onChange={handleChange}/>
</form>
</div>
);
}
Have modified the code where USeState's correct return format is being used,. rather than Object it returns array.
Following is the codesandbox link:
https://codesandbox.io/s/trusting-elbakyan-9h2sn?file=/src/SignIn.js
import React from "react";
import { useState } from "react";
export default function SignIn() {
const [ forInp, setForm ] = useState({
email: "abc#gmail.com",
password: ""
});
function handleChange(event) {
setForm({
...forInp,
[event.target.name]: event.target.value
});
}
function handleSubmit(event) {
event.preventDefault();
setForm({ [event.target.name]: "" });
}
return (
<div>
<form onSubmit={handleSubmit}>
<input
type="email"
name="email"
value={forInp.email}
placeholder="Email"
onChange={handleChange}
/>
<input
type="Password"
name="password"
value={forInp.password}
placeholder="Password"
onChange={handleChange}
/>
</form>
</div>
);
}
The correct way to useState is like
const[forInp,setForm]=useState({
email:"abc#gmail.com",
password:""
});
we need to set two variable in array and assigned this array from useState
Here is reference link
https://reactjs.org/docs/hooks-state.html
You need to change this:
const{forInp,setForm}=useState({
email:"abc#gmail.com",
password:""
});
to this:
const [ forInp, setForm ] = useState({
email: "abc#gmail.com",
password: ""
});
Explanation:
React.useState returns an Array of [ state, function ], not an Object.

Why onSubmit is not working with React ES6 syntax?

I am a newbie in React world. Actually, I come across a situation. When I use modern syntax, I am not getting things done. But, with bind.this method everything is working smoothly. Below is my code. Can you please find out mistakes. It giver error like "cant find state of undefined". Thank you.
import React, { Component } from 'react';
class Login extends Component {
state = {
email: '',
password: '',
}
handleChange = e => {
this.setState({ [e.target.name]: e.target.value });
};
signin(e) {
e.preventDefault();
const { email, password } = this.state;
if (email === 'xyz#gmail.com' && password === '123456') {
console.log('logged in')
}
}
render() {
return(
<div className='login'>
<div className='login-div'>
<form
onSubmit={this.signin}>
<fieldset>
<h2 className='heading'>Sign into your account</h2>
<label htmlFor="email">
<input
type="email"
name="email"
placeholder="email"
value={this.state.email}
onChange={this.handleChange}
/>
</label>
<label htmlFor="password">
<input
type="password"
name="password"
placeholder="password"
value={this.state.password}
onChange={this.handleChange}
/>
</label>
<button type="submit">Sign In!</button>
</fieldset>
</form>
</div>
</div>
)
}
}
export default Login;
can you change your function to this
signin = (e) => {
e.preventDefault();
const { email, password } = this.state;
if (email === 'xyz#gmail.com' && password === '123456') {
console.log('logged in')
}
}
Just to explain what's going on :
It's because inside signin function, this refers to the context of the execution (the event handler) but not to your React component.
You can specify which this the signin function will be bound to using bind method.
Add this line at the begining of the class :
this.signin = this.signin.bind(this);
Note : You can avoid binding all your functions by writing them using arrow function syntax.

React Form Validation

I've just started learning react and I am doing a simple form app.
And my question is how can I validate the text and email inputs?
I've tried few ways to do it but the code it's getting really messy so I removed the code w/ 'validation'
Here's my code this is my parent 'Form' component
import React, { Component } from "react";
import Name from "components/Name";
import Email from "components/Email";
import Select from "components/Select";
import Bio from "components/Bio";
// Create Form Component
class Form extends Component {
constructor(props) {
super(props);
this.state = {
firstName: "",
lastName: "",
email: "",
country: "Norway",
bio: ""
};
}
// Handle inputs value on change event
handleChange = event => {
this.setState({
[event.target.id]: event.target.value
});
};
// Handle the form submission
handleSubmit = event => {
event.preventDefault();
// Send POST Request (every postbin expires aftre 30min)
fetch("https://postb.in/1580328526126-6915104780346", {
method: "POST",
mode: "no-cors",
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "*"
},
body: JSON.stringify(this.state)
});
console.log(this.state);
// Clear form inputs
this.setState({
firstName: "",
lastName: "",
email: "",
country: "",
bio: ""
});
};
// Render Form Component and its child components
render() {
// Destructuring the current component state
const { firstName, lastName, email, country, bio } = this.state;
return (
<form onSubmit={this.handleSubmit}>
<div className="shape rectangle"></div>
<div className="shape triangle"></div>
<div className="shape circle"></div>
<Name
firstName={firstName}
lastName={lastName}
handleChange={this.handleChange}
/>
<Email email={email} handleChange={this.handleChange} />
<Select country={country} handleChange={this.handleChange} />
<Bio bio={bio} handleChange={this.handleChange} />
<button type="submit" className="btn">
Submit
</button>
</form>
);
}
}
export default Form;
And here's a child component the rest of the child components are similar to this one.
import React, { Component } from "react";
// Create Name component for name && email inputs
class Name extends Component {
// Render labels and name inputs
render() {
const { firstName, lastName, handleChange } = this.props;
return (
<div className="form-names">
<label htmlFor="firstName">Name</label>
<br />
<input
type="text"
name="firstName"
value={firstName}
placeholder="First Name"
id="firstName"
onChange={handleChange}
required
/>
<input
type="text"
name="lastName"
value={lastName}
placeholder="Last Name"
id="lastName"
onChange={handleChange}
required
/>
</div>
);
}
}
export default Name;
https://react-hook-form.com/
There are a few libraries you can use for doing form validation in react. Basically you will just have a form validation function that uses things like regex comparisons and conditionals that these libraries support. The link above provides a comparison to some popular libraries.

This handleSubmit() is not working when I move my Form to a different file

I am following the Scrimba tutorial on React but I decided to move my Form to a new file/component and change the functions to ES6.
Can someone tell me why? Thanks!
Now the handle Submit is not working (it works when the form is rendered in Meme Generator) but I don't know why and it doesn't throw any errors.
import React, { Component } from 'react'
import Form from "./Form"
class MemeGenerator extends Component {
constructor() {
super()
this.state = {
topText: "",
bottomText: "",
randomImg: "http://i.imgflip.com/1bij.jpg",
allMemeImgs: []
}
}
componentDidMount() {
fetch("https://api.imgflip.com/get_memes").then(response => response.json())
.then(response => {
const {memes} =response.data
console.log(memes[2])
this.setState({allMemeImgs: memes})
})
}
handleChange = (event) => {
const {name, value} = event.target
this.setState({[name]: value})
}
handleSubmit = (event) => {
event.preventDefault()
const randNum = Math.floor(Math.random() *
this.state.allMemeImgs.length)
const randMemeImg = this.state.allMemeImgs[randNum].url
this.setState({ randomImg: randMemeImg})
}
render() {
return (
<Form
handleChange = {this.handleChange}
data={this.state}
onSubmit={this.handleSubmit}
/>
)
}
}
export default MemeGenerator
The image is supposed to update to a random image every time the button is clicked. But it doesn't, also the whole page reloads, ignoring the event prevent Default
import React from 'react'
import style from './styles.module.css'
function Form(props) {
return (
<div>
<form className={style.memeForm} onSubmit={props.handleSubmit}>
<input
type="text"
placeholder="Type your top text"
name="topText"
value={props.data.topText}
onChange={props.handleChange}
/>
<input
type="text"
placeholder="Type your bottom text"
name="bottomText"
value={props.data.bottomText}
onChange={props.handleChange}
/>
<button>Generate</button>
</form>
<div className={style.meme}>
<img src={props.data.randomImg} alt="" />
<h2 className={style.top}>{props.data.topText}</h2>
<h2 className={style.bottom}>{props.data.bottomText}</h2>
</div>
</div>
)
}
export default Form
change these lines of code
onSubmit={(event) => props.handleSubmit(event)}
and
<button type='submit'>Generate</button>
<form className={style.memeForm} onSubmit={(event) => props.handleSubmit(event)}>
<input
type='text'
placeholder='Type your top text'
name='topText'
value={props.data.topText}
onChange={props.handleChange}
/>
<input
type='text'
placeholder='Type your bottom text'
name='bottomText'
value={props.data.bottomText}
onChange={props.handleChange}
/>
<button type='submit'>Generate</button>
</form>;

Categories

Resources