Let me tell you in brief what I am trying to do. As I am learning React, so following a tutorial and making a Contact Manager, where it will take input of name and email address for now and will save it in local storage. When I will reload the page, it will retrieve data from local storage and display it. As I am in a learning phase, I am just exploring how the state works and how I can save data in local storage, Later I will save these data to a DB.
React version I am using is:
 react: "18.1.0"
 react-dom: "18.1.0"
and my node version is:
17.1.0
I am setting the form input data to local storage by doing this:
   useEffect(() => {
    localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(contacts));
  }, [contacts]);
and retriving these data from local storage with the below code:
  useEffect(() => {
    const retriveContacts = JSON.parse(localStorage.getItem(LOCAL_STORAGE_KEY));
    if (retriveContacts) {
      setContacts(retriveContacts);
    }
  }, []);
I can see data is being stored in local storage from the Chrome Dev tool but whenever I am reloading the page, my goal is to retrieve the data from local storage and show the list. But after reloading, these data are not any longer visible on the page. I tried to debug, then I noticed, that when I am reloading the page, it's hitting the app.js component twice, the first time it's getting the data, but the second time the data is being lost.
I got a solution here, where it's saying to remove the React.StrictMode from index.js and after doing so it's working fine.
Then I tried to replace the current index.js with the previous react version (17.0.1) index.js. This is the code I tried:
import React from "react";
import ReactDOM from "react-dom";
import App from "./components/App";
ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById("root")
);
With this code, even with React.StrictMode this seems to work fine, I mean my data does not clear from local storage after reloading.
My question is, what's the reason behind it? Am I missing something or there is some logic behind it? The solution link I have provided is 4 years ago, and React 18 was released some time ago, can't figure out what actually I am doing wrong!
Any help or suggestions will be appreciated.
Below are the components to regenerate the scenario.
Current index.js (version 18.1.0)
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./components/App";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);
App.jsx
import React, { useState, useEffect } from "react";
import "../style/App.css";
import Header from "./Header";
import AddContact from "./AddContact";
import ContactList from "./ContactList";
function App() {
  const LOCAL_STORAGE_KEY = "contacts";
  const [contacts, setContacts] = useState([]);
  const addContactHandler = (contact) => {
    console.log(contact);
    setContacts([...contacts, contact]);
  };
  useEffect(() => {
    const retriveContacts = JSON.parse(localStorage.getItem(LOCAL_STORAGE_KEY));
    if (retriveContacts) {
      setContacts(retriveContacts);
      console.log(retriveContacts);
    }
  }, []);
  useEffect(() => {
    localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(contacts));
  }, [contacts]);
  return (
    <div className="ui container">
      <Header />
      <AddContact addContactHandler={addContactHandler} />
      <ContactList contacts={contacts} />
    </div>
  );
}
export default App;
Header.jsx
import React from 'react';
const Header = () => {
    return(
        <div className='ui fixed menu'>
            <div className='ui center container'>
                <h2>
                    Contact Manager
                </h2>
            </div>
        </div>
    );
};
export default Header;
ContactList.jsx
import React from "react";
import ContactCard from "./ContactCard";
const ContactList = (props) => {
  const listOfContact = props.contacts.map((contact) => {
    return <ContactCard contact={contact}></ContactCard>;
  });
  return <div className="ui celled list">{listOfContact}</div>;
};
export default ContactList;
AddContact.jsx
import React from "react";
class AddContact extends React.Component {
  state = {
    name: "",
    email: "",
  };
  add = (e) => {
    e.preventDefault();
    if (this.state.name === "" || this.state.email === "") {
      alert("ALl the fields are mandatory!");
      return;
    }
    this.props.addContactHandler(this.state);
    this.setState({ name: "", email: "" });
  };
  render() {
    return (
      <div className="ui main">
        <h2>Add Contact</h2>
        <form className="ui form" onSubmit={this.add}>
          <div className="field">
            <label>Name</label>
            <input
              type="text"
              name="name"
              placeholder="Name"
              value={this.state.name}
              onChange={(e) => this.setState({ name: e.target.value })}
            />
          </div>
          <div className="field">
            <label>Email</label>
            <input
              type="text"
              name="email"
              placeholder="Email"
              value={this.state.email}
              onChange={(e) => this.setState({ email: e.target.value })}
            />
          </div>
          <button className="ui button blue">Add</button>
        </form>
      </div>
    );
  }
}
export default AddContact;
ContactCard.jsx
import React from "react";
import user from '../images/user.png'
const ContactCard = (props) => {
    const {id, name, email} = props.contact;
    return(
        <div className="item">
        <img className="ui avatar image" src={user} alt="user" />
        <div className="content">
            <div className="header">{name}</div>
            <div>{email}</div>
        </div>
        <i className="trash alternate outline icon"
            style={{color:"red"}}></i>
    </div>
    );
};
export default ContactCard;
App.css
.main {
  margin-top: 5em;
}
.center {
  justify-content: center;
  padding: 10px;
}
.ui.search input {
  width: 100%;
  border-radius: 0 !important;
}
.item {
  padding: 15px 0px !important;
}
i.icon {
  float: right;
  font-size: 20px;
  cursor: pointer;
}