我在每次刷新或重新加载时从本地存储渲染数据时遇到问题。它只渲染硬编码数据,而不渲染我保存在 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;
我花了一些时间,但我想我有一个例子可能会做你所描述的事情。看来下面的代码可能是罪魁祸首:
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
@科林黑尔的答案非常有效。但是,您也可以使用箭头函数修改联系人的 useState,而不是编写单独的 useEffect 挂钩来获取项目。
const [contacts, setContacts] = useState(()=>{
const retrieved_contacts = JSON.parse(localStorage.getItem("contacts"));
return [] ? retrieved_contacts==null : retrieved_contacts
})