ReactJS remember me component to hooks

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

>Solution :

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.

setEmail({ email: localStorage.username });

Invocations like that should be just

setEmail(localStorage.username);

and so on.

You also don’t need useEffect(); just use useState‘s function initialization:

import React, { useState } from "react";

function Me() {
  // State, initial state loaded from local storage if set
  const [email, setEmail] = useState(() => (localStorage.checkbox ? localStorage.username : ""));
  const [password, setPassword] = useState(() => (localStorage.checkbox ? localStorage.password : ""));
  const [isChecked, setIsChecked] = useState(() => !!localStorage.checkbox);

  const loginSubmit = () => {
    if (isChecked && email !== "") {
      localStorage.username = email;
      localStorage.password = password;
      localStorage.checkbox = isChecked ? "1" : "";
      alert("Okay!");
    }
  };

  return (
    <div>
      <form>
        <table align="center">
          <tr>
            <td>
              <label>Email</label>
            </td>
            <td>
              <input type="email" name="email" value={email} onChange={(e) => setEmail(e.target.value)} />
            </td>
          </tr>
          <tr>
            <td>
              <label>Password</label>
            </td>
            <td>
              <input type="password" name="password" value={password} onChange={(e) => setPassword(e.target.value)} />
            </td>
          </tr>
          <tr>
            <td colSpan="2">
              <input
                type="checkbox"
                checked={isChecked}
                name="lsRememberMe"
                onChange={(e) => setIsChecked(e.target.checked)}
              />
              <label>Remember me</label>
            </td>
          </tr>
          <tr>
            <td colSpan="2">
              <input type="button" value="Login" onClick={loginSubmit} />
            </td>
          </tr>
        </table>
      </form>
    </div>
  );
}

Leave a Reply