在 React 应用程序中从本地存储渲染数据时出现问题

问题描述 投票:0回答:2

我在每次刷新或重新加载时从本地存储渲染数据时遇到问题。它只渲染硬编码数据,而不渲染我保存在 LS 中的数据。它在LS中显示数据但不渲染。如果有人能解释或告诉我出了什么问题,或者给我指示去做更好的事情,我将不胜感激。我对 React 还很陌生,并且会感谢您的见解。我放置了一些虚拟数据。我已经发送了可能会影响的组件。

import { useState, useEffect } from "react";
//COMPONENTS:
import ScrollToTop from "./components/ScrollToTop";
import Footer from "./components/Footer";
import Home from "./components/Home";
import NavBar from "./components/NavBar";
import PhoneBook from "./components/PhoneBook";

function App() {
  const date = new Date().toLocaleDateString();
  const [contacts, setContacts] = useState([
    {
      id: Math.random().toString(36).substr(2, 9),
      fullName: "Vekjko Petrovic",
      address: "121 Town Commons Way Phoenix, AZ, 45215",
      phone: 123_465_689,
      date,
    },
    {
      id: Math.random().toString(36).substr(2, 9),
      fullName: "Marko Petrovic",
      address: "Srbina 35, 11300 Smederevo Srbija",
      phone: 256_269_866,
      date,
    },
    {
      id: Math.random().toString(36).substr(2, 9),
      fullName: "Michael Jackson",
      address: "52 City St, Detroit, Mi, 46218",
      phone: 359_525_555,
      date,
    },
    {
      id: Math.random().toString(36).substr(2, 9),
      fullName: "Vanessa Parady",
      address: "11 Beogradska Beograd, SRB, 11000",
      phone: 123_465_689,
      date,
    },
  ]);

  useEffect(() => {
    const savedContacts = JSON.parse(localStorage.getItem("contacts"));

    if (savedContacts) {
      setContacts(savedContacts);
    }
  }, []);

  useEffect(() => {
    localStorage.setItem("contacts", JSON.stringify(contacts));
  }, [contacts]);

  const [searchContact, setSearchContact] = useState("");

  const [theme, setTheme] = useState("dark");
  const changeTheme = () => {
    theme === "dark" ? setTheme("light") : setTheme("dark");
  };

  const addContact = (fullName, phone, address, email) => {
    const newContacts = {
      id: Math.random().toString(36).substr(2, 9),
      fullName,
      address,
      phone,
      email,
      date,
    };
    const newContact = [...contacts, newContacts];
    setContacts(newContact);
  };

  const deleteContact = (id) => {
    const remainedContacts = contacts.filter((item) => item.id !== id);
    setContacts(remainedContacts);
  };

  return (
    <div data-theme={theme} className="app-container">
      <ScrollToTop />
      <NavBar changeTheme={changeTheme} currentTheme={theme} />
      <Home />
      <PhoneBook
        contacts={contacts.filter((contact) =>
          contact.fullName.toLowerCase().includes(searchContact)
        )}
        handleAddContact={addContact}
        deleteContact={deleteContact}
        handleSearchContacts={setSearchContact}
      />
      <Footer />
    </div>
  );
}

export default App; 

import React from "react";

import "../index.css";

//ASSETS:

import NewContact from "./NewContact";
import Contact from "./Contact";
import Search from "./Search";

function PhoneBook({
  contacts,
  handleAddContact,
  deleteContact,
  handleSearchContacts,
}) {
  return (
    <div id="phone_book" className="contacts-list">
      <Search handleSearchContacts={handleSearchContacts} />

      {contacts.map((contact) => {
        return (
          <Contact
            key={contact.id}
            id={contact.id}
            fullName={contact.fullName}
            address={contact.address}
            phone={contact.phone}
            email={contact.email}
            date={contact.date}
            deleteContact={deleteContact}
          />
        );
      })}

      <NewContact handleAddContact={handleAddContact} />
    </div>
  );
}

export default PhoneBook;

import React from "react";
import profile from "../assets/images/profile.png";
import { MdDeleteForever } from "react-icons/md";
function Contact({ fullName, address, phone, email, id, date, deleteContact }) {
  return (
    <div className="contact">
      <p className="contact-header">
        <span>
          <i>{fullName} </i>
        </span>
        <img src={profile} alt="profile" />
      </p>
      <div className="contact-footer">
        <p>
          {" "}
          <i>Address: </i>
          {address}
        </p>
        <p>
          <i>Phone:</i> {phone}
        </p>
        <p>
          {" "}
          <i>Email:</i> {email}
        </p>
        <MdDeleteForever
          onClick={() => deleteContact(id)}
          className="delete-icon"
          size="1.3rem"
        />
        <p className="span-date">
          <i>Date: </i>
          {date}
        </p>
      </div>
    </div>
  );
}

export default Contact;

import React, { useState } from "react";

function NewContact({ handleAddContact }) {
  const [fullName, setFullName] = useState("");
  const [phone, setPhone] = useState("");
  const [address, setAddress] = useState("");
  const [email, setEmail] = useState("");

  const handleSaveClick = () => {
    if (!(fullName.trim().length > 0)) {
      return;
    }
    handleAddContact(fullName, phone, address, email);
    setFullName("");
    setPhone("");
    setAddress("");
    setEmail("");
  };

  return (
    <div className="contact new last">
      {" "}
      <p className="inputs">
        <span>Create New Contact</span>

        <label>Full Name:</label>
        <input
          type="text"
          placeholder="Enter..."
          value={fullName}
          onChange={(e) => setFullName(e.target.value)}
        />
        <label> Address:</label>
        <input
          type="text"
          placeholder="Enter..."
          value={address}
          onChange={(e) => setAddress(e.target.value)}
        />
        <label> Phone:</label>
        <input
          type="text"
          placeholder="Enter..."
          value={phone}
          onChange={(e) => setPhone(e.target.value)}
        />
        <label>Email:</label>
        <input
          type="text"
          placeholder="Enter..."
          value={email}
          onChange={(e) => setEmail(e.target.value)}
        />
      </p>
      {/* <img src={profile} alt="fullname" /> */}
      <div className="save-list-footer">
        <button className="save" onClick={handleSaveClick}>
          SAVE
        </button>
      </div>
    </div>
  );
}

export default NewContact;
import styled from "styled-components";
import React from "react";
import { MdSearch } from "react-icons/md";

//STYLES
import "../index.css";

function Search({ handleSearchContacts }) {
  return (
    <SearchComponent className="search">
      <MdSearch className="search-icon" size="1.3em" />
      <input
        type="text"
        placeholder="Search..."
        onChange={(e) => handleSearchContacts(e.target.value)}
      />
    </SearchComponent>
  );
}
export default Search;
javascript html reactjs json rendering
2个回答
0
投票

我花了一些时间,但我想我有一个例子可能会做你所描述的事情。看来下面的代码可能是罪魁祸首:

  useEffect(() => {
    localStorage.setItem("contacts", JSON.stringify(contacts));
  }, [contacts]);

不在您的示例中,我假设您正在像这样初始化联系人:

const [contact, setContacts] = useState([])

初始化此状态时,它将触发 useEffect 并设置 localStorage.setItem("contacts" , []) 这将使它看起来像没有渲染任何内容。我认为最简单的解决方法是将 localStorage.setItem 移至 addContacts 函数中。

以下是如何设置的简化版本:

export const Contacts = () => {
  const [contacts, setContacts] = useState([]);

  useEffect(() => {
    const savedContacts = localStorage.getItem("contacts");

    if (savedContacts) {
      setContacts(JSON.parse(savedContacts));
    }
  }, []);

  // useEffect(() => {
  //   //This is your issue here Comment out this block and comment in the setItem in the addContact
  //  localStorage.setItem("contacts", JSON.stringify(contacts));
  // }, [contacts]);

  const addContact = (newContact) => {
    const newContactList = [...contacts, newContact];
    setContacts(newContactList);
    localStorage.setItem("contacts", JSON.stringify(newContactList));
  };

  return (
    <div>
      <InputContact addContact={addContact} />
      {contacts.map((data, i) => (
        <Contact data={data} key={i} />
      ))}
    </div>
  );
};

您可以在代码沙箱上找到这方面的工作示例。 App.js 和 Contacts.jsx 中有该应用程序的一些说明。 https://codesandbox.io/s/localstorage-contacts-s9dfzc?file=/src/Contacts.jsx:130-969


0
投票

@科林黑尔的答案非常有效。但是,您也可以使用箭头函数修改联系人的 useState,而不是编写单独的 useEffect 挂钩来获取项目。

const [contacts, setContacts] = useState(()=>{
  const retrieved_contacts = JSON.parse(localStorage.getItem("contacts"));
  return [] ? retrieved_contacts==null : retrieved_contacts
})
© www.soinside.com 2019 - 2024. All rights reserved.