I am working on a login form, and I am getting a strange behavior whereby whenever I click on the 'Login' button, the page simply reloads, without logging in my email and password through the 'submitHandler' function.
Below is a code of the form (I removed a lot of extra CSS formatting and div's).
Here is a screenshot of the form:
loginForm
import React from 'react'
import { useState, useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { login } from "../../../actions/userActions";
import { Form, Button, Row, Col } from "react-bootstrap";
function LoginForm ({history}) {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const submitHandler = (e) => {
e.preventDefault();
console.log(email, password)
// dispatch(login(email, password));
};
return (
<form>
<button onSubmit={submitHandler} type="submit">
Login
</button>
</form>
)
}
export default LoginForm
Does anyone have idea why the page reloads after clicking on the login button?
Issue
The button is of type="submit" but the form has no onSubmit handler and is thus taking the default form action, i.e. submitting the form and reloading the page.
Solution
Move the onSubmit to the form element so the callback can prevent the default form action from occurring.
<form onSubmit={submitHandler}>
<button type="submit">
Login
</button>
</form>
You can also convert button type="" method provider submit to button, in some cases you don't really want to submit internal form so just keep in mind.
Here is the example,
<form>
<button onSubmit={submitHandler} type="button">
</form>
Other answer is also OK, but I would like to approach from a different angle.
Try calling the submitHandler with onSubmit on the form instead of on the button.
Related
I am using svelte with an on:click event on a button. When this button is clicked, I dispatch some information to a higher component. What I would like to do is hit the enter key instead, but on:keydown doesn't seem to work? How can I get this to fire when hitting enter?
<button on:click={() =>
dispatch('search', { searchword: item })}
>ClickMe</button>
<button on:keydown={() =>
dispatch('search', { searchword: item })}
>PressEnter</button>
Enter will automatically fire click if the button has focus or is part of a form and is clicked implicitly as part of the form submission.
Generally I would recommend using a form, then Enter within an <input> will cause a form submission. One can then also directly work with the form's submit event, as that may need cancelling anyway, unless the page reload is desired.
Example:
<script>
let value = '';
let submittedValue = null;
</script>
<form on:submit|preventDefault={() => submittedValue = value}>
<label>
Search
<input bind:value />
</label>
<button on:click={() => console.log('button clicked')}>GO</button>
</form>
{#if submittedValue != null}
<p>Submitted: {submittedValue}</p>
{/if}
REPL
The issue was a state machine giving focus/ not giving focus. This project was using xstate to manage alot.
I have a react component
const Header = () => {
return(
<div role="button" className="user-logout" onClick={logoutUser}>
<i className="fas fa-sign-out-alt user--nav--icon"></i>
Logout
</div>
)}
In the above code onClick logout the user gets logged out
const logoutUser = () => {
dispatch(logout());
history.push('/login');
};
but I want the user to get a message popup onClcik in a div with conforming logout or cancel
and then on confirming logout it should logout the user
You can pass a GET Parameter to the login page like:
history.push('/login?logout=1');
Then if the login page has this parameter, render your message.
If you don't want to use a parameter, you will have to look for another solution either with react context or react navigation
For example, I created a Root Component named Index.vue, and Registred these 3 Login, Agree and Validation. What I'm picturing out is, after click submit button inside Login, the Agree.vue is showed and successively is happen when I click submit button inside Agree.
I think that I should use prop data to passing among components a state about each components, that way trigged a command to show the component that I want. But how I should "hide" the other components. I don't know if there a way to register the component at the moment submit form inside each Login, Agree, ...
<template>
<v-app>
<Login />
<Agree />
<Validation />
</v-app>
</template>
<script>
export default {
components:{
Login: () => import('./components/Login'),
Agree: () => import('./components/Agree-Term')
Validation: () => import('./components/Validation')
}
}
</script>
GOAL:
I am making a login by Google functionality in my website using Firebase Auth. I want When the user clicks the Signin link in the Navbar, he is redirected to the login page, in the login page, there is a dummy email/password input form and a Login with Google Button. When the user clicks on the Login with Google button he should be redirected to all the email list, so that he can choose from which he wants to login.
ERROR:
When the user clicks on the Signin Link in the Navbar the Login Route opens up and the function for the firebase auth is called by itself, without even clicking the Google Signin Button and the user is redirected to the emails list page.
Login.jsx:
import React from 'react'
import {Link} from "react-router-dom"
import './components/css/login.css'
import googleLogo from "./components/svg/google.svg"
import brandLogo from "./components/img/logo1.png"
//The JS for Login is in another file
import { googleSignin } from './firebase/googleLogin'
function login() {
return (
<div className="background-div" >
<nav className="login-nav" >
<img src={brandLogo} alt="logo"/>
<h2>the<strong>Dukaandar</strong></h2>
</nav>
<form action="" className="login-form">
<h3><strong>Login into your account</strong></h3>
<h5 className="login-email" >Email</h5>
<input type="text" className="login-email-input" placeholder="Enter your email" />
<h5 className="login-password">Password</h5>
<input type="password" className="login-password-input" placeholder="Enter your password" />
<br />
<button className="login-button">Login</button>
<Link className="login-forgot-password">forgot password?</Link>
<hr />
// The onClick attribute in React, I expect anything to happen only after clicking this button
<button className="google-login" onClick={googleSignin()} > <span className="google-image"><img src={googleLogo} alt=""/></span>Login with Google</button>
<Link to={"/"}>Back to Home</Link>
</form>
</div>
)
}
export default login
JS File:
import firebase from 'firebase'
const firebaseConfig = {
// Key value pairs of my config
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
//This is the Function which has to be called on button click
function googleSignin() {
var provider = new firebase.auth.GoogleAuthProvider();
firebase
.auth()
.signInWithRedirect(provider)
.then(function(result) {
// This gives you a Google Access Token. You can use it to access the Google API.
var token = result.credential.accessToken;
// The signed-in user info.
var user = result.user;
console.log(user);
console.log(result);
})
.catch(function(error) {
console.log(error);
});
}
export { googleSignin }
While searching for it I came to know about lifecycle methods which occurs when the component is rendered, if that is the case here, how to stop them to call itself?
As told in answer below and from my finding onClick{ () => googleSignin } also does not work, and also when I call the function with parenthesis googleSignin(), the function is atleast called but withot it nothing hapens.
I suspect there can be a React Router problem also, but I don't know.
Thank you in advance
Full Source Code of the Website on Github,
Live Preview on Netlify
By adding parenthesis on the onClick handler, you are invoking the function as soon as it is loaded. Remove the parenthesis and it will work.
<button className="google-login" onClick={googleSignin}>
<span className="google-image">
<img src={googleLogo} alt="" />
</span>
Login with Google
</button>
When the Browser sees the function is being called and not referenced on the OnClick method, it takes the responsibility and calls the function by itself. So, we have to free the Browser from its responsibility, and let the Function to be called only when the User clicks on the button.
Make a Handler function to free the Browser from its responsibility:
function handleClick(e) {
e.preventDefault();
googleSignin();
console.log('The link was clicked.');
}
Reference handleClick in your onClick method:
<button className="google-login"
//Reference handleClick here.
onClick={handleClick}>
<span className="google-image">
<img src={googleLogo} alt=""/>
</span>
Login with Google
</button>
This will solve the problem.
In the below code, I am trying to console.log the form input value when a button gets clicked. However, upon the button click, the value is only getting logged momentarily before disappearing.
why is this happening and how to resolve it?
document.querySelector("button").addEventListener("click",function(){
const listItem = document.querySelector("input").value;
console.log(listItem);
});
<body>
<form action="">
<input type="text">
<button class ="btn btn-lg btn-primary" type="submit"> ADD </button>
</form>
</body>
When submitting a form, the browser sends a request to the server and refreshes the page. To disable this behavior, you can use event.preventDefault() when clicking the button
document.querySelector("button").addEventListener("click",function(event){
event.preventDefault();
const listItem = document.querySelector("input").value;
console.log(listItem);
});
<body>
<form action="">
<input type="text">
<button class ="btn btn-lg btn-primary" type="submit"> ADD </button>
</form>
</body>
Others have explained that submitting a form reloads the page. But that doesn't really address the question about the console log.
Go to the Developer Tools settings, and in the Console section check Preserve log upon navigation. Then you won't lose log messages when the page reloads because of the form submission.
This is because browser reloads on the form submission. And your data is lost.
To prevent this simply use "event.preventDefault()" function after your log statement after passing "event" as a parameter in the event listener function.
Like this:
document.querySelector("button").addEventListener("click", function (event) {
const listItem = document.querySelector("input").value;
console.log(listItem);
event.preventDefault();
});