Scoping during Login with React and react-redux-firebase - reactjs

I am using react-redux-firebase for authentication and user management.Once users login, I want to navigate the user to their dashboard with an url of 'dahboard/userId.' When the user authenticate firebase gives us a response that has the user's ID there. The problem is when I attempt to complete a nav request via 'this.history.push('dahsboard/uid') I keep getting an error that says 'this' is undefined. I'm pretty sure it is a scoping issue but I cannot figure out exactly how I need to structure the code to solve the problem.
I have already tried to store the uid as a const. I have also tried chaining another async funciton to the request. Either this.props is undefined or the uid is undefined.
onSubmit = (e) => {
e.preventDefault();
// this.props.signIn(this.state);
this.props.firebase.login(this.state)
.then(function(res){
const userId = res.user.user.uid;
console.log(userId);
this.props.push('/dashboard/userId');
// ! Scoping issue - How to get 'props' in or userId out of this scope
})
.catch(
err => console.log(err.message),
)
}
render() {
const authError = this.props.authError;
return(
<div className="container">
<div className="row">
<div className="col-sm-9 col-md-7 col-lg-5 mx-auto">
<div className="card card-signin my-5">
<div className="card-body">
<div className = "red-text center">
{authError ? <p> {authError.message} </p> : null}
</div>
<h5 className="card-title text-center">Sign In</h5>
<form className="form-signin" onSubmit={this.onSubmit}>
<div className="form-label-group">
<label>Email address
<input type="email" id="inputEmail" className="form-control" placeholder="Email address" value={this.state.email} onChange={this.onChangeEmail} required autoFocus />
</label>
</div>
<div className="form-label-group">
<label>Password
<input type="password" id="inputPassword" className="form-control" placeholder="Password"
value={this.state.password}
onChange={this.onChangePassword}
required />
</label>
</div>
<div className="custom-control custom-checkbox mb-3">
<input type="checkbox" className="custom-control-input" id="customCheck1" />
<label className="custom-control-label" >Remember password
</label>
</div>
<button className="btn btn-lg btn-primary btn-block text-uppercase" type="submit">Sign in</button>
<hr className="my-4" />
</form>
</div>
</div>
</div>
</div>
</div>
)
}
}
export default compose(
//map firebase redux to props
firebaseConnect((props) => {
}),
connect(
//map redux-state to props
(state) => ({
userId: state.firebase.auth.uid,
authError: state.firebase.authError,
auth: state.firebase.auth
})
)
)(Login)

You need to use withRouter from "react-router" like so:
export default withRouter(connect(mapStateToProps, {
...
})(App));
Then it will be accessible through this.props;
You can also pass history through props from App if you have a nested component like so:
<NestedComponent history={this.props.history}/>

Related

Trying to have multiple input elements

But when i use handle input change function it erases the entire object and replaces it with one property
Also If someone can help me reset the form data? because I'm setting state to the initial state value but the text fields arent erasing.
const initialState = {
name: '',
number: '',
message: '',
email: '',
messageSent: false,
};
//State After typingState
{email: "2"}
I was using a class-based component and it was working fine I switched over and now I am getting one property on submit instead of 4
I would like for the handle change to change a particular property and not the entire object
stepped away from react for a while an d not sure what to google fo this fix. Tried
Handling Multiple inputs Functional Components React etc..
let handleInputChange = (event) => {
const target = event.target;
const value = target.value;
const name = target.name;
setstate({
[name]: value,
});
}
return (
<section
id="contact-form"
className={
GrayBg === true
? 'contact-form-area_3'
: 'contact-form-area_3 contact-page-version'
}
>
<div className="container">
<div className="section-title mb45 headline text-center">
<span className="subtitle text-uppercase">Send us a message</span>
<h2>
Send Us A<span> Message.</span>
</h2>
</div>
<div className="contact_third_form">
<form
className="contact_form"
encType="multipart/form-data"
onSubmit={ sendEmail}
>
<div className="row">
<div className="col-md-4">
<div className="contact-info">
<input
className="name"
name="name"
type="text"
value={state.value}
onChange={handleInputChange}
placeholder="Your Name."
/>
</div>
</div>
<div className="col-md-4">
<div className="contact-info">
<input
className="email"
name="email"
type="email"
value={state.value}
onChange={handleInputChange}
placeholder="Your Email"
/>
</div>
</div>
<div className="col-md-4">
<div className="contact-info">
<input
className="number"
name="number"
type="number"
value={state.value}
onChange={handleInputChange}
placeholder="Phone Number"
/>
</div>
</div>
</div>
<textarea
name="message"
placeholder="Message."
value={state.value}
onChange={handleInputChange}
></textarea>
<div className="nws-button text-center gradient-bg text-uppercase">
<button id="contact-button" type="submit">
{state.messageSent ? 'Sent!' : 'Send'}{' '}
<i
className={
state.messageSent
? 'fas fa-check'
: 'fas fa-caret-right'
}
></i>
</button>
</div>
</form>
</div>
</div>
State updates are not merged with hooks unlike in class components, you need to do so yourself.
Update your state using a functional approach to setState and by spreading the rest of the values within the returned object like
setstate(prev => ({
...prev,
[name]: value,
}));

How to Validate an Email address in React using functional components?

I am working on a React project in that project I have a form, In that form I am trying to do
Validation for an email address, but I don't know how to apply all these.
What I am expecting is, In input tag if I type mark, then If I go to another Input tag it has to
Show me some kind of message above Input tag like this, please enter a valid email address.
This is Form.js
import React from 'react';
import './Form.css';
const Form = () => {
const validation = (email) => {
const result = /^(([^<>()\[\]\\.,;:\s#"]+(\.[^<>()\[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return result.test(String(email).toLowerCase());
}
return (
<div className='container'>
<div className='row'>
<div className='col-4'>
<div className='mainForm'>
<form>
<div className="form-group">
<label htmlFor="exampleInputEmail1">Email address</label>
<input type="email" className="form-control" id="exampleInputEmail1" aria-describedby="emailHelp" />
</div>
<div className="form-group">
<label htmlFor="exampleInputPassword1">Password</label>
<input type="password" className="form-control" id="exampleInputPassword1" />
</div>
<button type="submit" className="btn btn-primary">Submit</button>
</form>
</div>
</div>
</div>
</div>
)
}
export default Form
I think those are basic problem in all JS code base, you need to catch the input event, using onChange, onBlur, On...etc and bind those event to your react class, like
return <input type=”email” name=”email” value={this.state.email}
onChange={this.handleChange.bind(this)}/>
then on the handleChange you can call the email validation
handleChange(event){
var email = event.target.value;
// do what ever you want
validation(email);
}

How to get a form to disapear upon submission in React

This is a 'contact us' form on a website.
I want all the cells of the form to disappear after the user clicks the 'submit' button upon 'success'. In other words, I wont the form to no longer be rendered if the submission is a success. Since this is React, I wouldn't want the page to do an old fashioned reload, just go away upon the condition.
The way it works now upon submission only the button disappears if the submission is a success and nothing disappears if the submission is a failure, which can remain the same.
This is a form that uses XML with a Google Apps Script to send the user's entered form data upon submission. This all works fine and there is something within the 'status' state working with the onSubmit action that is making the Conditional Rendering not so straight forward.
IF YOU WOULD LIKE TO TEST THIS IN REACT TO WORK IT OUT
Since I don't want to put my email code there you should make the 'else' condition that sets 'status' to say 'SUCCESS' near the bottom at 'this.setState({ status: "ERROR" });' so the if/ else in the email sending function (at the bottom) will render the form as if the data went through and the email was sent. My suggestion.
The code below is how the component works normally but my attempt to solve this problem was to store all the cells above as a variable and 'return' it if 'status' was > 0. Because status is "" before the button is pressed. This just caused the whole page to reload, re-rendering the whole DOM and not sending the email.
import React from 'react';
export default class MyForm extends React.Component {
constructor(props) {
super(props);
this.submitForm = this.submitForm.bind(this);
this.state = {
status: ""
};
}
render() {
const { status } = this.state;
return (
<form
onSubmit={this.submitForm}
action="https://script.google.com/macros/s/000000AKfycbz000000000C0/exec"
method="POST"
>
<div className="row_10" style={{"margin-top": "30px"}}>
<div className="col-25">
</div>
<div className="col-75">
<input type="text" id="name" name="Name" placeholder="Name:"/>
</div>
</div>
<div className="row_10">
<div className="col-25">
</div>
<div className="col-75">
<input type="text" id="Phone" name="Phone" placeholder="Phone:"/>
</div>
</div>
<div className="row_10">
<div className="col-25">
</div>
<div className="col-75">
<input type="text" id="Email" name="Email" placeholder="Email:"/>
</div>
</div>
<div className="row_10">
<div className="col-25">
</div>
</div>
<div className="row_10">
<div className="col-25">
</div>
<div className="row_10">
<textarea className="col-75_T" id="subject" name="subject" placeholder="How can we help you?" style={{"height": "190px"}}></textarea>
</div>
</div>
<div className="subm_button">
<div className="col-25">
</div>
</div>
{status === "SUCCESS" ? <p>Thank you! We will talk to you soon!</p> :<input onClick="fbq('track', 'Contact');" type="submit" value="Submit"/>}
{status === "ERROR" && <p>Ooops! There was an error.</p>}
</form>
);
}
submitForm(ev) {
ev.preventDefault();
const form = ev.target;
const data = new FormData(form);
const xhr = new XMLHttpRequest();
xhr.open(form.method, form.action);
xhr.setRequestHeader("Accept", "application/json");
xhr.onreadystatechange = () => {
if (xhr.readyState !== XMLHttpRequest.DONE) return;
if (xhr.status === 200) {
form.reset();
this.setState({ status: "SUCCESS" });
} else {
this.setState({ status: "ERROR" });
}
};
xhr.send(data);
}
}
Apply the same logic you have with your message to your form
renderForm() {
return (
<form
onSubmit={this.submitForm}
action="https://script.google.com/macros/s/000000AKfycbz000000000C0/exec"
method="POST"
>
<div className="row_10" style={{"margin-top": "30px"}}>
<div className="col-25">
</div>
<div className="col-75">
<input type="text" id="name" name="Name" placeholder="Name:"/>
</div>
</div>
<div className="row_10">
<div className="col-25">
</div>
<div className="col-75">
<input type="text" id="Phone" name="Phone" placeholder="Phone:"/>
</div>
</div>
<div className="row_10">
<div className="col-25">
</div>
<div className="col-75">
<input type="text" id="Email" name="Email" placeholder="Email:"/>
</div>
</div>
<div className="row_10">
<div className="col-25">
</div>
</div>
<div className="row_10">
<div className="col-25">
</div>
<div className="row_10">
<textarea className="col-75_T" id="subject" name="subject" placeholder="How can we help you?" style={{"height": "190px"}}></textarea>
</div>
</div>
<div className="subm_button">
<div className="col-25">
<input onClick="fbq('track', 'Contact');" type="submit" value="Submit"/>
</div>
</div>
</form>
);
}
render() {
const { status } = this.state;
const submitted = status === "SUCCESS";
return (
<>
{!submitted && this.renderForm()}
{submitted && <p>Thank you! We will talk to you soon!</p>}
{status === "ERROR" && <p>Ooops! There was an error.</p>}
</>
);
}

"Expected an assignment but found an expression"

I'm working on a project with my classmates, but while trying to load this page in react I get the error: "Expected an assignment or function call and instead saw an expression" that's appeared on several of her pages. I looked into it and it seems to be a warning that ES Lint throws out, but I'm unsure of how to fix it for my particular issue. Any help would be appreciated.
Code Snippet::
import React from "react";
import './LoginPage.css';
import GlobalNav from '../../components/GlobalNav';
import GlobalFooter from '../../components/GlobalFooter/GlobalFooter';
const LoginPage = props => {
<div>
<GlobalNav />
<h1 className="uk-text-center blueText">login</h1>
<div className="uk-container"/>
<form className="authorForm uk-width-1-2#m uk-align-center uk-form-stacked">
<p className="uk-text-lead">Login and add some Highlights of your own.</p>
<p className="uk-text-center redText"><span uk-icon="bolt"></span></p>
<fieldset className="uk-fieldset">
<div className="form-group">
<div className="uk-margin">
<label className="uk-form-label" for="form-stacked-select">* Email:</label>
<div className="uk-inline uk-width-1-1">
<span className="uk-form-icon uk-form-icon-flip blueText" uk-icon="icon: world"></span>
<input className="uk-input" id="email" name="email" type="text"></input>
</div>
</div>
<div className="uk-margin">
<label className="uk-form-label" for="form-stacked-select">* Password:</label>
<div className="uk-inline uk-width-1-1">
<span className="uk-form-icon uk-form-icon-flip blueText" uk-icon="icon: lock"></span>
<input className="uk-input" id="password" name="password" type="text"></input>
</div>
</div>
<button className="uk-button uk-button-secondary redText uk-align-center" id="submit-btn"><span uk-icon="user"></span> login</button>
</div>
</fieldset>
</form>
<GlobalFooter />
</div>
}
export default LoginPage;
You forgot to enclose them in a return statement.
const LoginPage = props => {
// this is where you put your logic if needed before returning JSX codes
return (
<div>
// ...rest of the codes
</div>
);
};
or, you can simply do this, since you're using ES6 arrow function:
const LoginPage = props => (
<div>
// ...rest of the code
</div>
);

Showing input value in the url link (ReactJs Laravel)

I created laravel project with the reactjs framework and I'm new for this framework. I have problem and why It happens every time i submit the form.
Goal: users can register through online
Problem:
Why it happens when i submit the button the input value of user shown in the url link?
The data that I input is not inserted to the database.
Code:
constructor() {
super();
this.state = {
f_name:'',
l_name:'',
m_name:'',
email:'',
home_num:'',
contact_num:'',
Job_name:[],
employ_status:'',
employ_relocate:'',
employ_start_date:'',
employ_file:''
}
this.handleSubmit = this.handleSubmit.bind(this);
this.handle_fname = this.handle_fname.bind(this);
this.handle_lname = this.handle_lname.bind(this);
this.handle_mname = this.handle_mname.bind(this);
this.handle_email = this.handle_email.bind(this);
this.handle_homenum = this.handle_homenum.bind(this);
this.handle_contactnum = this.handle_contactnum.bind(this);
this.handle_employ_status = this.handle_employ_status.bind(this);
this.handle_employ_relocate = this.handle_employ_relocate.bind(this);
this.handle_employ_start_date = this.handle_employ_start_date.bind(this);
this.handle_employ_file = this.handle_employ_file.bind(this);
}
componentDidMount() {
const id = this.props.match.params.id;
axios.get('/api/online_application_job_title/' +id).then(response => {
this.setState({
Job_name:response.data
})
})
}
handleSubmit(e)
{
const data = {
firstname: this.state.f_name,
lastname : this.state.l_name,
middlename : this.state.m_name,
email : this.state.email,
home_number : this.state.home_num,
contact_num : this.state.contact_num,
job : this.state.Job_name[0].position_name,
employ_status : this.state.employ_status,
employ_relocate : this.state.employ_relocate,
employ_start_date : this.state.employ_start_date,
employ_file : this.state.employ_file
}
axios.post('/api/save_application',data).then(response => {
console.log(response);
}).catch(error => console.log(error));
}
handle_fname(e)
{
this.setState({
f_name:e.target.value,
})
}
handle_lname(e){
this.setState({
l_name:e.target.value,
})
}
handle_mname(e){
this.setState({
m_name:e.target.value,
})
}
handle_email(e){
this.setState({
email:e.target.value,
})
}
handle_homenum(e){
this.setState({
home_num:e.target.value
})
}
handle_contactnum(e){
this.setState({
contact_num:e.target.value
})
}
handle_employ_status(e){
this.setState({
employ_status:e.target.value
});
}
handle_employ_relocate(e){
this.setState({
employ_relocate:e.target.value,
})
}
handle_employ_start_date(e){
this.setState({
employ_start_date:e.target.value,
})
}
handle_employ_file(e){
this.setState({
employ_file: e.target.files[0].extension
})
}
renderName() {
return (
this.state.Job_name.map(name => (
<input placeholder="" value={name.position_name} type="text" className="form-control"/>
))
)
}
render() {
return (
<div>
<div className="header">
<div className="jumbotron">
<h1>Online Application</h1>
</div>
</div>
<form onSubmit={this.handleSubmit}>
<div className="container">
<h5><b>Personal Info</b></h5>
<br/>
<div className="row">
<div className="col-md-6">
<input
placeholder="First Name*"
value={this.state.f_name}
onChange={this.handle_fname}
className="form-control"/>
</div>
<div className="col-md-6">
<input
placeholder="Last Name*"
value={this.state.l_name}
onChange={this.handle_lname}
className="form-control"/>
</div>
</div>
<br/>
<div className="row">
<div className="col-md-6">
<input
placeholder="Middle Name*"
value={this.state.m_name}
onChange={this.handle_mname}
className="form-control"/>
</div>
<div className="col-md-6">
<input
placeholder="Email Address*"
type="email"
value={this.state.email}
onChange={this.handle_email}
className="form-control"/>
</div>
</div>
<br/>
<div className="row">
<div className="col-md-6">
<input
placeholder="Home Number*"
type="number"
value={this.state.home_num}
onChange={this.handle_homenum}
className="form-control"/>
</div>
<div className="col-md-6">
<input
placeholder="Contact Number*"
type="number"
value={this.state.contact_num}
onChange={this.handle_contactnum}
className="form-control"/>
</div>
</div>
<br/><br/>
<h5><b>Employment Application</b></h5>
<br/>
<div className="row">
<div className="col-md-6">
<p>Position Applying For</p>
{this.renderName()}
</div>
<div className="col-md-6">
</div>
</div>
<br/><br/>
<div className="row">
<div className="col-md-6">
<p>1. What is your current employment status?</p>
<div className="form-check-inline">
<label className="form-check-label">
<input
type="radio"
className="form-check-input"
name="employmentstatus"
onChange={this.handle_employ_status}
defaultChecked={false}
value="Unemployed"/>Unemployed
</label>
</div>
<div className="form-check-inline">
<label className="form-check-label">
<input
type="radio"
className="form-check-input"
name="employmentstatus"
onChange={this.handle_employ_status}
defaultChecked={false}
value="Employed"/>Employed
</label>
</div>
<div className="form-check-inline disabled">
<label className="form-check-label">
<input
type="radio"
className="form-check-input"
name="employmentstatus"
onChange={this.handle_employ_status}
defaultChecked={false}
value="Self-Employed"/>Self-Employed
</label>
</div>
<div className="form-check-inline disabled">
<label className="form-check-label">
<input
type="radio"
className="form-check-input"
name="employmentstatus"
onChange={this.handle_employ_status}
defaultChecked={false}
value="Student"/>Student
</label>
</div>
</div>
<div className="col-md-6"></div>
</div>
<br/>
<div className="row">
<div className="col-md-6">
<p>2. Are you willing to relocate?</p>
<div className="form-check-inline">
<label className="form-check-label">
<input type="radio"
name="relocate"
onChange={this.handle_employ_relocate}
className="form-check-input"
value="Yes"/>Yes
</label>
</div>
<div className="form-check-inline">
<label className="form-check-label">
<input type="radio"
name="relocate"
onChange={this.handle_employ_relocate}
className="form-check-input"
value="No"/>No
</label>
</div>
</div>
<div className="col-md-6"></div>
</div>
<br/>
<div className="row">
<div className="col-md-6">
<p>3. When is your available start date?</p>
<input
name="startdate"
type="date"
onChange={this.handle_employ_start_date}
value={this.state.employ_start_date}
required=""
className="form-control"/>
</div>
<div className="col-md-6"></div>
</div>
<br/>
<div className="row">
<div className="col-md-6">
<p>4. Kindly attach a copy of your resume (PDF,docx files only).</p>
<div className="custom-file">
<input
type="file"
name="file"
accept="application/msword,application/pdf"
onChange={this.handle_employ_file}
className="custom-file-input"
id="inputGroupFile04"/>
<label className="custom-file-label" htmlFor="inputGroupFile04">Choose file</label>
</div>
</div>
<div className="col-md-6"></div>
</div>
<br/>
<div className="row">
<div className="col-md-6">
<input
className="btn btn-outline-primary btn-large form-control col-md-5"
type="submit"
value="Send Application"/>
</div>
<div className="col-md-6"></div>
</div>
</div>
</form>
</div>
)
}
Controller:
public function save_application(Request $request)
{
$firstname = $request->get('firstname');
$lastname = $request->get('lastname');
$middlename = $request->get('middlename');
$email = $request->get('email');
$home_number = $request->get('home_number');
$contact_num = $request->get('contact_num');
$job = $request->get('job');
$employ_status = $request->get('employ_status');
$employ_relocate = $request->get('employ_relocate');
$employ_start_date = $request->get('employ_start_date');
$employ_file = $request->get('employ_file');
$now = new DateTime();
DB::insert('INSERT INTO onlineapplication
(position_name,firstname,middlename,lastname,email,homenumber,phonenumber,employmentstatus,relocate,starting_date,destination,file_img_name,Status)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)',[
$firstname,
$lastname,
$middlename,
$email,
$home_number,
$contact_num,
$job,
$employ_status,
$employ_relocate,
$employ_start_date,
$employ_file
]);
return response()->json('Successfully inserted');
}
When form tag is used, the submit will trigger the default behaviour that is based on the method provided and the action url.
as in your example you are handling the data explicitly you should prevent the default behaviour.
add the below code in handle submit
handleSubmit(e) {
e.preventDefault();
...
...
}
this will prevent the default behaviour.
Improvement for state update:
you don't need individual functions to update the input value to state this can be combined in one function.
to combine, provide the input name same as state name.
this.state ={
"f_name": '',
"l_name": '',
...
}
<input name="f_name" ... onChange={this.handleInputChange}/>
<input name="l_name" .. onChange={this.handleInputChange}/>
handleInputChange(e){
let target = e.target;
let name = target.name;
let value = target.value
this.setState({[name]: value})
}
for more info refer this link.
First, I just want to introduce to you to the arrow function in JavaScript (ES6). Declaring private methods like this:
handle_fname = (e) =>
{
this.setState({
f_name:e.target.value,
})
}
will save you time from unnecessary binding in the constructor.
Regarding your question, you missed to show the content of your this.handleSubmit(). Without this, I can assume that the form submit fired a get call since you failed to put method attribute in your <form/> tag, and without indicating your method attribute will result to default get method. Get method when used, data submitted will be visible in the page address field of your browser.
EDIT
You already added your handleSubmit() in your question, and it looks okay. If data is still shown in the address field of your browser, try adding method="post" in your form tag like this:
<form onSubmit={this.handleSubmit} method="post">

Resources