我有这个问题,每当我刷新FeedbackDetailView页面,反馈状态在FeedbackDetailView被清除,这是有意的,但我正在寻找一种方法来坚持反馈数据。我尝试使用useEffect()来调用API,但是useEffect()在页面刷新时不运行,因此刷新后状态仍然被清除。然而,当FeedbackDetail从'/'路由导航时,状态就在那里,组件也能很好地渲染注释。我使用上下文来保存来自API调用的反馈数据,当主页呈现时,但反馈状态仍然刷新,并试图将反馈数据保存到localStorage,但仍然无法获得反馈数据。有人能帮忙吗?谢谢!
FeedbackDetailView.js
import { useParams, Link } from "react-router-dom";
import { useState, useContext, useEffect } from "react";
import ButtonTertiary from "../Elements/Buttons/ButtonTertiary";
import FeedbackDetail from "../FeedbackView/FeedbackDetail";
import FeedbackDetailComment from "./FeedbackDetailComment";
import FeedbackContext from "../../contexts/FeedbackContext";
const FeedbackDetailView = () => {
const { feedbacks } = useContext(FeedbackContext);
const id = useParams().id.slice(0, -1);
const feedback = feedbacks.find((feedback) => feedback.id === id);
return (
<div className="p-6 sm:mx-28 md:max-w-xl md:mx-auto">
<div className="mt-8">
<Link to="/">
<ButtonTertiary buttonText="Go Back" />
</Link>
</div>
<FeedbackDetail feedback={feedback} />
<div className="p-6 bg-white rounded-lg mt-14 md:mx-auto">
<h1 className="text-lg font-bold text-navy-primary">
{feedback.comments.length}{" "}
{feedback.comments.length === 1 ? "Comment" : "Comments"}
</h1>
{feedback.comments.length !== 0 ? (
<div className="mt-2 border-grey-50">
{feedback.comments.map((comment, index) => (
<FeedbackDetailComment key={index} comment={comment} />
))}
</div>
) : (
""
)}
</div>
<div className="p-6 bg-white rounded-lg mt-14 md:mx-auto">
<h1 className="text-lg font-bold text-navy-primary">Add a comment</h1>
<p className="text-sm font-light text-navy-tertiary">
Max 250 characters.
</p>
<textarea className="mt-4 bg-main-secondary text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full h-24 p-2.5"></textarea>
<div className="flex w-full justify-items-end">
<button
type="submit"
className="px-6 py-3 mt-4 ml-auto text-sm font-semibold leading-5 text-center text-white rounded-lg cursor-pointer text-b bg-fuchsia-600 hover:bg-fuchsia-400"
>
Add Comment
</button>
</div>
</div>
</div>
);
};
export default FeedbackDetailView;
Homepage.js
const Homepage = () => {
const [open, setOpen] = useState(false);
const [showFeedbacks, setShowFeedbacks] = useState(false);
const [sortOption, setSortOption] = useState("Most Upvotes");
const [selectedCategory, setSelectedCategory] = useState("All");
const { feedbacks, setFeedbacks } = useContext(FeedbackContext);
const { message, type } = useContext(NotificationContext);
const { setLoggedInUser } = useContext(UserContext);
useEffect(() => {
feedbackService.getAll().then((initialFeedbacks) => {
setFeedbacks(initialFeedbacks.sort((a, b) => b.upvotes - a.upvotes));
});
}, []);
useEffect(() => {
const loggedUserJson = window.localStorage.getItem("loggedFeedbackAppUser");
if (loggedUserJson) {
const user = JSON.parse(loggedUserJson);
setLoggedInUser(user);
feedbackService.setToken(user.token);
}
}, []);
useEffect(() => {
if (feedbacks.length > 0) {
setShowFeedbacks(true);
}
}, [feedbacks.length]);
const handleSlideoverOpen = () => {
setOpen(!open);
};
const updateSortOption = (sort) => {
setSortOption(sort);
};
const sortedFeedbacks = (feedbacks) => {
if (sortOption === "Most Upvotes") {
return feedbacks.sort((a, b) => b.upvotes - a.upvotes);
} else if (sortOption === "Least Upvotes") {
return feedbacks.sort((a, b) => a.upvotes - b.upvotes);
} else if (sortOption === "Most Comments") {
return feedbacks.sort((a, b) => b.comments.length - a.comments.length);
} else if (sortOption === "Least Comments") {
return feedbacks.sort((a, b) => a.comments.length - b.comments.length);
}
};
return (
<div className="container p-0 mx-auto sm:mt-14 md:px-9">
<Alerts type={type} message={message} />
{/* When screen is > 1024px (Desktop Screens) */}
<div className="hidden lg:contents">
<div className="flex flex-row gap-x-8">
<div className="flex flex-col gap-y-6">
<Hero handleSlideoverOpen={handleSlideoverOpen} open={open} />
<FeedbackCategory />
</div>
<div className="flex flex-col w-full">
<FeedbackNavbar
feedbackNum={feedbacks.length}
sortOption={sortOption}
updateSortOption={updateSortOption}
/>
<FeedbackList
feedbacks={sortedFeedbacks(feedbacks)}
showFeedbacks={showFeedbacks}
sortOption={sortOption}
/>
</div>
</div>
</div>
{/* When screen is > 768px (Tablet Screens) */}
<div className="hidden sm:contents lg:hidden">
<div className="flex flex-row justify-between mb-10">
<Hero handleSlideoverOpen={handleSlideoverOpen} open={open} />
<FeedbackCategory
selectedCategory={selectedCategory}
setSelectedCategory={setSelectedCategory}
/>
</div>
</div>
{/* When screen is < 640px (Mobile Screens) */}
<div className="sm:hidden">
<Hero handleSlideoverOpen={handleSlideoverOpen} open={open} />
</div>
<div className="hidden">
<FeedbackCategory />
</div>
{/* Slideover */}
<div className="sm:hidden">
<Slideover open={open} setOpen={handleSlideoverOpen} />
</div>
<div className="lg:hidden">
<FeedbackNavbar
feedbackNum={feedbacks.length}
sortOption={sortOption}
updateSortOption={updateSortOption}
/>
<FeedbackList feedbacks={feedbacks} showFeedbacks={showFeedbacks} />
</div>
</div>
);
};
export default Homepage;
FeedbackContext.js
import { createContext, useState, useEffect } from "react";
const FeedbackContext = createContext();
export const FeedbackProvider = ({ children }) => {
const [feedbacks, setFeedbacks] = useState([]);
return (
<FeedbackContext.Provider value={{ feedbacks, setFeedbacks }}>
{children}
</FeedbackContext.Provider>
);
};
export default FeedbackContext;
App.js
import { Route, Routes } from "react-router-dom";
import Homepage from "./components/Homepage/Homepage";
import AddFeedbackForm from "./components/AddFeedback/AddFeedbackForm";
import LoginPage from "./components/Login/LoginPage";
import RegisterPage from "./components/Login/RegisterPage";
import FeedbackDetailView from "./components/FeedbackView/FeedbackDetailView";
import { NotificationProvider } from "./contexts/NotificationContext";
import { UserProvider } from "./contexts/UserContext";
import { FeedbackProvider } from "./contexts/FeedbackContext";
const App = () => {
return (
<div>
<FeedbackProvider>
<UserProvider>
<NotificationProvider>
<Routes>
<Route path="/" element={<Homepage />} exact />
<Route path="/add-feedback" element={<AddFeedbackForm />} />
<Route path="/login" element={<LoginPage />} />
<Route path="/register" element={<RegisterPage />} />
<Route path="/feedbacks/:id" element={<FeedbackDetailView />} />
</Routes>
</NotificationProvider>
</UserProvider>
</FeedbackProvider>
</div>
);
};
export default App;
移动获取和设置feedbacks
状态的useEffect
钩子到设置FeedbackProvider
,以便在it时获取它安装并将其提供给消费者,如FeedbackDetailView
组件安装时。从Home
组件中删除useEffect
钩子。
FeedbackContext
import { createContext, useState, useEffect } from "react";
const FeedbackContext = createContext();
export const FeedbackProvider = ({ children }) => {
const [feedbacks, setFeedbacks] = useState([]);
useEffect(() => {
feedbackService.getAll().then((initialFeedbacks) => {
setFeedbacks(initialFeedbacks.sort((a, b) => b.upvotes - a.upvotes));
});
}, []);
return (
<FeedbackContext.Provider value={{ feedbacks, setFeedbacks }}>
{children}
</FeedbackContext.Provider>
);
};
export default FeedbackContext;
如果您需要通过页面重载来持久化feedbacks
状态,那么您将希望将其持久化更长时间,例如localStorage。feedbacks
状态可以直接从localStorage初始化。