How can I show the updated state? - reactjs

When I'll click submit, it will save in the firestore, however, I still need to reload the page to update the state. How can I code it in a way that once I'll click submit, it will immediately reflect on the screen without reloading it?
const Account = () => {
const [displayName, setdisplayName] = useState(currentUser.displayName);
const [address, setAddress] = useState(currentUser.address);
const handleSubmit = async (event) => {
event.preventDefault();
try {
const userRef = firestore.collection("users").doc(currentUser.id);
const res = userRef.set(
{
displayName,
address,
},
{ merge: true }
);
} catch (err) {
console.log(err);
}
};
return (
<div>
<form onSubmit={handleSubmit}>
<TextField
placeholder={currentUser.displayName}
value={displayName}
color="secondary"
required
onChange={(e) => setdisplayName(e.target.value)}
/>
<TextField
type="text"
placeholder={currentUser.address}
value={address}
onChange={(e) => setAddress(e.target.value)}
required
/>
<Button type="submit">Submit</Button>
</form>
</div>
);
};
export default MyAccount;

You can use 1 flag to mark when it submit,use useState update value of flag and page will change.
const Account = () => {
const [displayName, setdisplayName] = useState(currentUser.displayName);
const [address, setAddress] = useState(currentUser.address);
const [flag,setFlag] = useState(false);
const handleSubmit = async (event) => {
event.preventDefault();
try {
const userRef = firestore.collection("users").doc(currentUser.id);
const res = userRef.set(
{
displayName,
address,
},
{ merge: true }
);
setFlag(true);
} catch (err) {
console.log(err);
}
};
return (
<div>
<form onSubmit={handleSubmit}>
<TextField
placeholder={currentUser.displayName}
value={displayName}
color="secondary"
required
onChange={(e) => setdisplayName(e.target.value)}
/>
<TextField
type="text"
placeholder={currentUser.address}
value={address}
onChange={(e) => setAddress(e.target.value)}
required
/>
<Button type="submit">Submit</Button>
</form>
</div>
);
};
export default MyAccount;

Related

i have problem with writing Page in react js?

I can't type in the fields for a page Login on React js and mdbootstrap and css
this is the problem please my developper Help me solve this problem I have suffered with it a lot What is the solution please help me with this problem
What is the root of this problem please fix my code
This is the problem code
import React, { useState } from 'react';
export default function App() {
const [iconsActive, setIconsActive] = useState('pill1');
const handleIconsClick = (value: string) => {
if (value === iconsActive) {
return;
}
setIconsActive(value);
};
const [values, setValues] = useState({
email: '',
password: '',
});
const [submitted, setSubmitted] = useState(false);
const [showSuccess, setShowSuccess] = useState(false);
const handleInputChange = (event) => {
event.persist();
setValues((values) => ({
...values,
[event.target.email]: event.target.value,
}));
};
const isFormValid = () => {
if (!values.email || !values.password) {
return false;
} else {
return true;
}
};
const handleSubmit = (e) => {
e.preventDefault();
setSubmitted(true);
if (isFormValid()) {
setShowSuccess(true);
}
};
return (
<div
className='text-center'
id='formm'
class='register-form'
onSubmit={handleSubmit}
>
{showSuccess && (
<div class='success-message'>Success! Thank you for registering</div>
)}
<MDBTabs pills justify className='mb-3'>
<MDBCol>
<MDBTabsItem>
<MDBTabsLink
onClick={() => handleIconsClick('pill1')}
active={iconsActive === 'pill1'}
>
<MDBIcon className='me-2' />
Login
</MDBTabsLink>
</MDBTabsItem>
</MDBCol>
<MDBTabsItem>
<MDBTabsLink
onClick={() => handleIconsClick('pill2')}
active={iconsActive === 'pill2'}
>
<MDBIcon className='me-2' />
Register
</MDBTabsLink>
</MDBTabsItem>
</MDBTabs>
<MDBTabsContent>
<MDBTabsPane show={iconsActive === 'pill1'}>
<MDBInput
className='mb-4'
type='email'
id='form7Example1'
label='Email address'
disabled={showSuccess}
value={values.email}
onChange={handleInputChange}
/>
{submitted && !values.email && (
<span id='email-error'>Please enter a email</span>
)}
<MDBInput
className='mb-4'
type='password'
id='form7Example2'
label='Password'
disabled={showSuccess}
value={values.password}
onChange={handleInputChange}
/>
{submitted && !values.password && (
<span id='password-error'>Please enter a last name</span>
)}
<MDBBtn type='submit' className='mb-4' block disabled={showSuccess}>
Sign in
</MDBBtn>
Your problem is here:
setValues((values) => ({
...values,
[event.target.email]: event.target.value,
}));
You are setting value to the wrong keys.
I would suggest you to create two states and separate handlers for every input OR you can do the following:
const handleInputChange = (type) => ({target}) => {
setValues((values) => ({
...values,
[type]: target.value,
}));
};
<MDBInput
value={values.email}
onChange={handleInputChange("email")}
/>
<MDBInput
value={values.password}
onChange={handleInputChange("password")}
/>

Form automatically submitting, why is preventDefault() not working

I recently created a link shortening application in react. I have a problem with the form automatically submitting when I enter a link, I have preventDefault() as you can see in the code and onSubmit in the form element.
const onSubmit = (e) => {
e.preventDefault();
return false;
}
if (!text){
} else {
const shortenLink = async () => {
const res = await fetch(`https://api.shrtco.de/v2/shorten?url=${text}`)
const data = await res.json()
console.log(data.result);
setLinks(data.result)
setText('')
}
shortenLink()
}
const copy = () => {
navigator.clipboard.writeText(links.full_short_link)
setButtonText('Copied!')
}
return (
<>
<Container>
<StyledInput onSubmit={onSubmit}>
<InputContainer>
<Input type="url" value={text} onChange={(e) => setText(e.target.value)} placeholder="Shorten link here..." required />
<ButtonTwo onClick={onSubmit} type="submit" bg="#666AF6" color="#fff">Shorten It!</ButtonTwo>
</InputContainer>
</StyledInput>

Firebase won't register user information

Firebase isn't registering my user's information.
I keep getting a warning saying: 'onAuthStateChanged' is defined but never used and
'user' is assigned a value but never used.
Also, when I enter the email and password it doesn't set to empty string even though I set my password and email both to ("").
import './App.css';
import { auth } from './firebase';
import { useState, useEffect } from 'react';
import {
signInWithEmailAndPassword,
onAuthStateChanged, //<-----Here's my problem
createUserWithEmailAndPassword,
} from 'firebase/auth';
function App() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [user, setUser] = useState([]); // <---------Here is the other issue
const [isSignUp, setIsSignUp] = useState(false);
useEffect(() => {
auth.onAuthStateChanged((user) => {
setUser(user);
});
});
const handleEmailChange = (e) => {
setEmail(e.target.value);
};
const handlePasswordChange = (e) => {
setPassword(e.target.value);
};
const signIn = async () => {
await signInWithEmailAndPassword(auth, email, password)
.then(() => {
setEmail('');
setPassword('');
})
.catch((error) => {
alert(error.message);
});
};
const register = async () => {
await createUserWithEmailAndPassword(auth, email, password).catch((error) =>
console.log(error.message)
);
setPassword('');
setEmail('');
};
return (
<div className="App">
{isSignUp ? (
<>
<h1>Registering...</h1>
<input
type="email"
placeholder="email"
value={email}
onChange={handleEmailChange}
/>
<input
type="password"
placeholder="password"
value={password}
onChange={handlePasswordChange}
/>
<button onClick={register}>Sign Up</button>
<button onClick={() => setIsSignUp(false)}>X</button>
</>
) : (
<>
<h1>Logging in...</h1>
<input
type="email"
placeholder="email"
value={email}
onChange={handleEmailChange}
/>
<input
type="password"
placeholder="password"
value={password}
onChange={handlePasswordChange}
/>
<button onClick={signIn}>Login</button>
<button onClick={() => setIsSignUp(true)}>Register</button>
</>
)}
</div>
);
}
export default App;
I see two mistakes.
First, you should use the modular syntax for your auth state handler:
useEffect(() => {
onAuthStateChanged((user) => { // 👈 Remove the auth. here
setUser(user);
});
});
And second, the default value of the user is an object, not an array:
const [user, setUser] = useState({});
There may be more problems, but these jumped out at me.
The actual solution to my problem was that I was in the wrong app in Firebase. Once I selected the right one from the dropdown menu it worked.

How to validate email and password using react hooks?

I am getting state values while clicking submit button but I am unable to do the validation for my login form and how to display the error messages below the input field when I enter my input wrong or empty. please give me a solution to this.Thanks in advance.
const Login = () => {
const [state, setState] = useState({
email: "",
password: ""
});
const handleChange = (e) => {
const {id, value} = e.target
setState(prevState => ({
...prevState,
[id]: value
}))
}
const handleSubmitClick = (e) => {
e.preventDefault();
console.log("Authenticated",state);
}
return(
<>
<div className="container">
<div className="title">
<form onSubmit={handleSubmitClick}>
<div className="form-group">
<input
type="email"
className="email"
placeholder="Email"
value={state.email}
onChange={handleChange}/>
</div>
<div className="form-group">
<input
type="password"
className="password"
placeholder="Password"
value={state.password}
onChange={handleChange}/>
</div>
<button type="submit" className="button">Enter</button>
</form>
</div>
</div>
</>
)
}
export default Login;
If you want to perform client-side validation, you can create hook like this:
const useEmailValidation = (email) => {
const isEmailValid = /#/.test(email); // use any validator you want
return isEmailValid;
};
And then you can use this hook in your form component:
...
const isEmailValid = useEmailValidation(state.email);
const isPasswordValid = usePasswordValidation(state.password);
const isFormValid = isEmailValid && isPasswordValid;
return (
...
<input
className={classNames({ 'invalid': !isEmailValid })}
type="email"
value={state.email}
onChange={handleChange}
/>
{!isEmailValid && 'Some error message'}
<button type="submit" disabled={!isFormValid} className="button">Enter</button>
...
);
...
Your validator hook can return validation message instead of boolean, like:
const useEmailValidation = (email) => {
if (!email || email.length === 0) {
return 'Email cannot be empty';
}
const isEmailValid = /#/.test(email); // use any validator you want
if (!isEmailValid) {
return 'Invalid email provided';
}
return null;
};
Also it is a good practice to show validation message only after field was focused before and after user tried to submit the form.
Formik is a great plugin that will help you perform form validation. The examples are also quite clear.
Or you could do something like this:
const Login = () => {
const [error, setError] = useState(null);
const [state, setState] = useState({
email: '',
password: '',
});
const validateEmail = (email) => {
const re =
/^(([^<>()[\]\\.,;:\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 re.test(String(email).toLowerCase());
};
const handleChange = (e) => {
const { id, value } = e.target;
setState((prevState) => ({
...prevState,
[id]: value,
}));
};
const handleSubmitClick = (e) => {
e.preventDefault();
if (!validateEmail(state.email)) {
setError('Invalid Email');
}
if (state.password.length < 8) {
setError('Password must be at least 8 chars long');
}
if (!error) {
// No errors.
}
};
return (
<>
<div className='container'>
<div className='title'>
{error && <div style={{ color: 'red' }}>{error}</div>}
<form onSubmit={handleSubmitClick}>
<div className='form-group'>
<input
type='email'
className='email'
placeholder='Email'
value={state.email}
onChange={handleChange}
/>
</div>
<div className='form-group'>
<input
type='password'
className='password'
placeholder='Password'
value={state.password}
onChange={handleChange}
/>
</div>
<button type='submit' className='button'>
Enter
</button>
</form>
</div>
</div>
</>
);
};
export default Login;
For an empty validation you can check it preventing the submit if the field is empty, like
const handleSubmitClick = (e) => {
e.preventDefault();
if(email.trim() === '' || password.trim() === ''){
//Add a h1 or section with the error message
}else{
console.log("Authenticated",state);
}
}
As long as the email field type is equal to email, which is your case, the browser should give an alert if the string is not an email. ("user#example.com")

How to fix memory leak in react?

const Register = () => {
const [username, setUsername] = useState("");
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [passConf, setPassConf] = useState("");
const [errors, setErrors] = useState([]);
const [loading, setLoading] = useState(false);
const [usersRef, setUsersRef] = useState(null);
const isPasswordValid = () => {
if (password.length < 6 || passConf.length < 6) {
return false;
} else if (password !== passConf) {
return false;
} else {
return true;
}
};
const isFormValid = () => {
let errors = [];
let error;
if (!isPasswordValid()) {
error = { message: "Password is invalid" };
setErrors(errors.concat(error));
return false;
} else {
return true;
}
};
const saveUser = (createdUser) => {
setUsersRef(firebase.database().ref("users"));
return usersRef.child(createdUser.user.uid).set({
name: createdUser.user.displayName,
avatar: createdUser.user.photoURL,
});
};
const handleSubmit = (event) => {
event.preventDefault();
if (isFormValid()) {
setErrors([]);
setLoading(true);
firebase
.auth()
.createUserWithEmailAndPassword(email, password)
.then((createdUser) => {
console.log(createdUser);
createdUser.user
.updateProfile({
displayName: username,
photoURL: `https://gravatar.com/avatar/${md5(
createdUser.user.email
)}?d=identicon`,
})
.then(() => {
saveUser(createdUser).then(() => {
console.log("user saved");
setLoading(false);
});
})
.catch((err) => {
setLoading(false);
setErrors(errors.concat(err));
});
})
.catch((err) => {
setLoading(false);
setErrors(errors.concat(err));
});
}
};
const displayErrors = (errors) =>
errors.map((error, i) => <p key={i}>{error.message}</p>);
return (
<Grid textAlign="center" verticalAlign="middle" className="app">
<Grid.Column style={{ maxWidth: 450 }}>
<Header as="h2" icon color="orange" textAlign="center">
<Icon name="rocketchat" color="orange" />
Register for Super Chat
</Header>
<Form onSubmit={handleSubmit} size="large">
<Segment stacked>
<Form.Input
fluid
name="username"
icon="user"
iconPosition="left"
type="text"
placeholder="Username"
value={username}
required
onChange={(e) => setUsername(e.target.value)}
/>
<Form.Input
fluid
name="email"
icon="mail"
iconPosition="left"
type="email"
placeholder="Email"
value={email}
required
onChange={(e) => setEmail(e.target.value)}
/>
<Form.Input
fluid
name="password"
icon="lock"
iconPosition="left"
type="password"
placeholder="Password"
value={password}
required
onChange={(e) => setPassword(e.target.value)}
/>
<Form.Input
fluid
name="passConf"
icon="repeat"
iconPosition="left"
type="password"
placeholder="Password Confirmation"
value={passConf}
required
onChange={(e) => setPassConf(e.target.value)}
/>
<Button disabled={loading} color="orange" fluid size="large">
Submit
</Button>
</Segment>
</Form>
{errors.length ? (
<Message error>
<h3>Error</h3>
{displayErrors(errors)}
</Message>
) : null}
<Message>
Already a user? <Link to="/login">Login</Link>
</Message>
</Grid.Column>
</Grid>
);
};
Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
I am not able to find where this memory leak is happening.
I am able to sign in with one account but after signing out and signing in again with another account, it's giving this warninng and firebase realtime database is also not updating.
How can I fix memory leak here?

Resources