I have a case here, which is to make a remember me function when logging in.
So, yesterday I got an online repo on codesandbox which contains reactjs component remember me.
Then I want to convert it into react hooks.
The code is like this (React Component original)
import React from "react";
class RememberMe extends React.Component {
static displayName = "RememberMe";
state = {
email: "",
password: "",
isChecked: false
};
componentDidMount() {
if (localStorage.checkbox && localStorage.email !== "") {
this.setState({
isChecked: true,
email: localStorage.username,
password: localStorage.password
});
}
}
onChangeValue = (event) => {
this.setState({
[event.target.name]: event.target.value
});
};
onChangeCheckbox = (event) => {
this.setState({
isChecked: event.target.checked
});
};
loginSubmit = () => {
const { email, password, isChecked } = this.state;
if (isChecked && email !== "") {
localStorage.username = email;
localStorage.password = password;
localStorage.checkbox = isChecked;
}
};
render() {
const { email, password, isChecked } = this.state;
return (
<div>
<form>
<table align="center">
<tr>
<td>
<label>Email</label>
</td>
<td>
<input
type="email"
name="email"
value={email}
onChange={this.onChangeValue}
/>
</td>
</tr>
<tr>
<td>
<label>Password</label>
</td>
<td>
<input
type="password"
name="password"
value={password}
onChange={this.onChangeValue}
/>
</td>
</tr>
<tr>
<td colSpan="2">
<input
type="checkbox"
checked={isChecked}
name="lsRememberMe"
onChange={this.onChangeCheckbox}
/>
<label>Remember me</label>
</td>
</tr>
<tr>
<td colSpan="2">
<input type="button" value="Login" onClick={this.loginSubmit} />
</td>
</tr>
</table>
</form>
</div>
);
}
}
export default RememberMe;
However, when it was finished, I tried to convert it into hooks, but it didn’t work properly, I thought, "Is there something wrong in my code? Thank you
import React, { useState, useEffect } from "react";
const Me = () => {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [isChecked, setIsChecked] = useState(false);
useEffect(() => {
if (localStorage.checkbox && localStorage.email !== "") {
setEmail({ email: localStorage.username });
setPassword({ password: localStorage.password });
setIsChecked({
isChecked: true
});
}
}, []);
const onChangeValue = (event) => {
setIsChecked({
[event.target.name]: event.target.value
});
};
const onChangeCheckbox = (event) => {
setIsChecked({
isChecked: event.target.checked
});
};
const loginSubmit = () => {
if (isChecked && email !== "") {
localStorage.username = email;
localStorage.password = password;
localStorage.checkbox = isChecked;
}
};
return (
<div>
<form>
<table align="center">
<tr>
<td>
<label>Email</label>
</td>
<td>
<input
type="email"
name="email"
value={email}
onChange={onChangeValue}
/>
</td>
</tr>
<tr>
<td>
<label>Password</label>
</td>
<td>
<input
type="password"
name="password"
value={password}
onChange={onChangeValue}
/>
</td>
</tr>
<tr>
<td colSpan="2">
<input
type="checkbox"
checked={isChecked}
name="lsRememberMe"
onChange={onChangeCheckbox}
/>
<label>Remember me</label>
</td>
</tr>
<tr>
<td colSpan="2">
<input type="button" value="Login" onClick={loginSubmit} />
</td>
</tr>
</table>
</form>
</div>
);
};
export default Me;
https://codesandbox.io/s/remember-me-localstorage-forked-crpt1z
2
Answers
Look closely at the types of your state.
Unlike with a class component where there’s one
state
object with various keys, each state atom is now separate and should just hold the value itself, yet you’re setting objects into them, e.g.Invocations like that should be just
and so on.
You also don’t need
useEffect()
; just useuseState
‘s function initialization:Yes, there’s a number of things wrong with your hooks code. Let’s go through a few of them in turn:
if (localStorage.checkbox && localStorage.email !== "") {
I notice that further down, you save the email like this
localStorage.username = email
. Why are you checkinglocalStorage.email
? Shouldn’t you be checkinglocalStorage.username
in your if statement instead?setEmail({ email: localStorage.username });
Try doing this instead:
setEmail(localStorage.username)
. You don’t need the wrapping object here. Same thing goes for the other two fields.setIsChecked
but expecting the other values to be updated? You’ll need to create a different handler for each field accordingly.onChange={onChangeValue}
like point 3 above, you’ll needonChange={onChangeEmail}
andonChange={onChangePassword}
as separate handlers.Functionality aside, there’s a number of additional things to consider:
If you make these changes you should get closer to a working project. Make sure you take the additional considerations into account before using your project anywhere in a real scenario!