Home > Back-end >  Reactjs - onChange continually clears input boxes, making it impossible to type something in
Reactjs - onChange continually clears input boxes, making it impossible to type something in

Time:01-11

I'm attempting to implement a login / signup form, however implementing onChange to set the state of the email / password makes it so the inputs are continually cleared onChange. This is obviously not the desired outcome, but I haven't seen anything about it online. Here is the code for the signup form.

import { React, useState } from "react";
import styled from "styled-components";
import { createUserWithEmailAndPassword } from "firebase/auth"
import { Link } from "react-router-dom";
import { auth } from '../Config/firebase.js';

// Import Assets //
import LogoPlaceholder from "../Assets/Login/LogoPlaceholder.png";

function LoginForm(props) {
  
const LoginFormContainer = styled.div`
    width: 80vw;
    margin-left: 10vw;
    height: 80vh;
    margin-top: 10vh;
    background-color: transparent;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
`;

const Logo = styled.img`
    margin-top: -150px;
    width: 325px;
    height: 180px;
`;

const SplashHeader = styled.h1`
    font-weight: 400;
    color: #333;
    word-spacing: 5px;
    letter-spacing: 0.5px;
    font-size: 3em;
    margin-top: 20px;
    text-align: center;
`;

const SplashText = styled.p`
    font-weight: 300;
    color: #333;
    word-spacing: 2px;
    letter-spacing: 0.5px;
    font-size: 1.5em;
    margin-top: 5px;
    width: 450px;
    text-align: center;
`;

const InputBox = styled.input.attrs(props => ({
    type: props.type || 'text', 
}))`
    width: 300px;
    height: 50px;
    font-size: 18px;
    padding-left: 10px;
    margin-top: 20px;
    border: 0;
    outline: 0;
    color: #fff;
    border-radius: 5px;
    background-color: #333;
    border-bottom: 3px solid transparent;
    transition: all 0.5s ease-in-out;

    &:focus {
        background-color: #3f3f3f;
        border-bottom-left-radius: 0;
        border-bottom-right-radius: 0;
        cursor: default;
        border-bottom: 3px solid #0026ED;
    }

    &::placeholder {
        color: #fafafa;
    }

    &:hover {
        cursor: pointer;
    }

    &:first-of-type {
        margin-bottom: 15px;
    }
`;

const SignupBtn = styled.button`
width: 125px;
height: 50px;
margin-top: 10px;
border: 0;
outline: 0;
border-radius: 5px;
margin-left: 13px;
transition: all 0.5s ease-in-out;
font-size: 18px;
background-color: #333;
color: #fafafa;
border: 3px solid transparent;

&:hover {
    border-radius: 10px;
    background-color: #3f3f3f;
    border: 3px solid #0026ED;
    cursor: pointer;
}
`;

const ButtonContainer = styled.div`
    width: 300px;
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: center;
`;

const StyledLink = styled(Link)` 
    color: #fafafa;
    text-decoration: none;
    font-size: 18px;
    font-weight: 300;
    border-bottom: 3px solid transparent;
    transition: all 0.5s ease-in-out;

    &:hover {
        cursor: pointer;
    }
`;

const StyledLinkDark = styled(Link)`
    color: #333;
    text-decoration: none;
    font-size: 16px;
    font-weight: 300;
    border-bottom: 3px solid transparent;
    transition: all 0.5s ease-in-out;

    &:hover {
        cursor: pointer;
    }
`;

const BackToLogin = styled.div`
    color: #000;
    margin-top: 5px;
    display: flex;
    flex-direction: row;
    align-items: center;
    width: 125px;
    justify-content: center;
    margin-left: 12px;
`;

const [registerEmail, setRegisterEmail] = useState("");
const [registerPassword, setRegisterPassword] = useState("");

const register = async () => {
    try {
        const user = await createUserWithEmailAndPassword(auth, registerEmail, registerPassword)
        console.log(user)
    } catch (error) {
        console.log(error.message);
    }
};

return(  
  <LoginFormContainer>
    <Logo src={LogoPlaceholder} alt="UDM Logo" />
    <SplashHeader>Uni-Deadline Manager Signup</SplashHeader>
    <SplashText>Sign up to Uni-Deadline Manager to keep track of all your unit deadlines in one place!</SplashText>
    <InputBox placeholder="Email" />
    <input type="text"  placeholder="email" onChange={(event) => {setRegisterEmail(event.target.value)}} />
    <InputBox name="password" onChange={(event) => {setRegisterPassword(event.target.value)}} marginTop="40px" placeholder="Password" type="password" />
    <InputBox name="password" placeholder="Confirm Password" type="password" />
    <ButtonContainer>
        <SignupBtn onClick={register}>
            <StyledLink to="/Signup">Signup</StyledLink>
        </SignupBtn>
    </ButtonContainer>
    <BackToLogin>
        <StyledLinkDark to="/">Back to login</StyledLinkDark>
    </BackToLogin>
  </LoginFormContainer>
)
}
export default LoginForm;

Any assistance on this (as far as I can see) relatively undocumented issue would be greatly appreciated.

CodePudding user response:

You have two problems here.

First, you don't use the value attribute of the input field, which will allow you to add characters:

<input type="text" value={registerEmail} placeholder="email" onChange={(event) => {setRegisterEmail(event.target.value)}} />

Second, as you said in the comments, your input looses focus after each character you type. This happens because react rerenders the screen each time you type a character. The reason react does this, is because you defined your components inside the body of the function (specifically I think it's the InputBox that causes this), which makes react rerender them each time they change.

The solution of this is to move the definition of these components outside of the scope of the function.

//Place them here
const LoginFormContainer = styled.div`
...`

function LoginForm(props) {
    //Remove from here
    const LoginFormContainer = styled.div`
    ...`

CodePudding user response:

It doesn't look like you are setting "value" on the <input tag. You need to set it to the state.

<input value={registerEmail} onChange=...

  •  Tags:  
  • Related