Not able to store data in local storage and use it on page refresh in React

Viewed 66

I'am using Firebase version 8.10.0 as the DB in my app, and I succeeded to show the data in my page. So generally Firebase consumes useEffect to show the data.

Also I succeeded to drag and drop the positions of table that contains firebase data. By my pain is to store the drag and drop positions in state and that state should be stored in localStorage.

My destination is to create a separate state that to be stored dragged items in localStorage. I tried this code but no result:

import React, { useState, useEffect, useRef } from "react";
import "./BootTable.css";
import "./Appa.css";
import "../node_modules/bootstrap/dist/css/bootstrap.min.css";
import firebaseDB from "./firebased";
import { ToastContainer, toast } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";

function App() {
  const dragItem = useRef();
  const dragOverItem = useRef();
  const [getData, setGetData] = useState({});

  //To Show the data    
  useEffect(() => {
    firebaseDB.child("register").on("value", (details) => {
      console.log(details.val());
      setGetData(details.val());
    });
  }, []);
 
  //To Store the dragged data into localStorage
  useEffect(() => {
    const data = window.localStorage.getItem("MY_DRAGGED_DATA");
    if (data !== null) setGetData(JSON.parse(data));
  }, []);
   
 //To set the item to localstorage

  useEffect(() => {
    console.log("show data", getData);

    window.localStorage.setItem("MY_DRAGGED_DATA", JSON.stringify(getData));
  }, [getData]);

  const deleteHandler = (key) => {
    firebaseDB.child(`register/${key}`).remove(() =>
      toast.error("Deleted!", {
        position: "top-right",
      })
    );
  };

  const dragStart = (e, position) => {
    dragItem.current = position;
    console.log(e.target.innerHTML);
  };

  const dragEnter = (e, position) => {
    dragOverItem.current = position;
    console.log(e.target.innerHTML);
  };
  const drop = (e) => {
    const copyListItems = [...Object.values(getData)];
    const dragItemContent = copyListItems[dragItem.current];
    copyListItems.splice(dragItem.current, 1);
    copyListItems.splice(dragOverItem.current, 0, dragItemContent);
    dragItem.current = null;
    dragOverItem.current = null;
    setGetData(copyListItems);
  };

  return (
    <div className="full_Container">
      <center>
        <h6 className="h6_heading">Winners</h6>
      </center>

      <table className="table " id="data-table">
        <thead className="table-hero">
          <tr>
            <th scope="col">S.no</th>
            <th className="put_pointer" scope="col">
              Name ▲▼
            </th>
            <th className="" scope="col">
              Company Name
            </th>
            <th className="put_pointer" scope="col">
              LTP
            </th>
            <th className="put_pointer" scope="col">
              %
            </th>
            <th className="put_pointer" scope="col">
              52 W.H
            </th>
            <th className="" scope="col">
              52 W.L
            </th>
            <th scope="col">M.B</th>
            <th className="" scope="col">
              Mkt.Cap
            </th>
            <th className="" scope="col">
              Volume
            </th>
            <th className="" scope="col">
              Zauba
            </th>
            <th className="" scope="col">
              M.C
            </th>
            <th className="" scope="col">
              N
            </th>
            <th className="" scope="col">
              C.I
            </th>
            <th className="" scope="col">
              Del
            </th>
          </tr>
        </thead>
        <tbody>
          {getData &&
            Object.keys(getData).map((key, index) => (
              <tr
                style={{ cursor: "move" }}
                onDragStart={(e) => dragStart(e, index)}
                onDragEnter={(e) => dragEnter(e, index)}
                onDragEnd={drop}
                key={index}
                draggablekey={index}
                draggable
              >
                <td>{index + 1}</td>

                <td>
                  <a
                    target="_blank"
                    style={{ color: "#212529" }}
                    href={getData[key].url}
                  >
                    {getData[key].name}
                  </a>
                </td>
                <td>
                  {" "}
                  <a
                    target="_blank"
                    style={{ color: "#212529" }}
                    href={getData[key].tradingview}
                  >
                    {getData[key].companyname}
                  </a>
                </td>
                <td>{getData[key].ltp}</td>
                <td>{getData[key].percent}</td>
                <td className="wk_low">{getData[key].weekhigh}</td>
                <td className="wk_low">{getData[key].weeklow}</td>
                <td className="wk_high">
                  {(getData[key].weekhigh / getData[key].weeklow).toFixed(2)}
                </td>
                <td>{getData[key].mcap}</td>
                <td>{getData[key].volume}</td>

                <td>
                  <a target="_blank" href={getData[key].zauba}>
                    <button
                      style={{
                        color: "#D39B16",
                        padding: "3px",
                        fontWeight: 1000,
                      }}
                      className="btn   btn-sm"
                    >
                      Z
                    </button>
                  </a>
                </td>
                <td>
                  <a target="_blank" href={getData[key].mc}>
                    <button
                      style={{
                        color: "#FF60AB",
                        padding: "3px",
                        fontWeight: 1000,
                      }}
                      className="btn  btn-sm"
                    >
                      M
                    </button>
                  </a>
                </td>
                <td>
                  <a target="_blank" href={getData[key].mc}>
                    <button
                      style={{
                        color: "#19be7b",
                        padding: "3px",
                        fontWeight: 1000,
                      }}
                      className="btn  btn-sm"
                    >
                      N
                    </button>
                  </a>
                </td>
                <td>
                  <a target="_blank" href={getData[key].ci}>
                    <button
                      style={{
                        color: "#19be7b",
                        padding: "3px",
                        fontWeight: 1000,
                      }}
                      className="btn  btn-sm"
                    >
                      C.I
                    </button>
                  </a>
                </td>
                <td>
                  <button
                    style={{ color: "#fff", padding: "3px", fontWeight: 1000 }}
                    className="btn  btn-sm btn-danger"
                    onClick={() => deleteHandler(key)}
                  >
                    Del
                  </button>
                </td>
                {/* {`https://roohhi.com/convert?name=${(filteredPerson.company.toLowerCase().replace(".",""))}` } */}
              </tr>

              //     <tr>{index}</tr>
              // <tr><a>{getData[key].url}{getData[key].companyname}</a></tr>
            ))}
        </tbody>
      </table>
      <ToastContainer theme="colored" />
    </div>
  );
}

export default App;
1 Answers

To have what you want you should first change how you are setting your initial state so that you pick what's in the localStorage if there is any and otherwise set it to null:

const [getData, setGetData] = useState(
  localStorage.getItem("MY_DRAGGED_DATA")
    ? JSON.parse(localStorage.getItem("MY_DRAGGED_DATA"))
    : null
);

And make sure you only use the data from Firebase if the initial data is null (I used null to have a falsy value) and that it's the first render (with loadRef), like so:

const loadRef = useRef(true);
useEffect(() => {
  firebaseDB.child("register").on("value", (details) => {
    if (getData && loadRef.current){
      loadRef.current = false;
      return
    }
    console.log(details.val());
    setGetData(details.val());
  });
}, []); // the linter might ask you to add getData in the dependency array but don't, and you will be fine.
Related