我正在使用 React 构建一个编程教程网站。每个内容页面都有一个侧边栏和一个主要内容部分,其中包含用于导航主题的“上一个”和“下一个”按钮。但是,当我在查看特定主题(例如第 10 个主题)时刷新页面时,它会重置为第一个主题,而不是停留在当前主题。
为了解决此问题,我将 currentHeadingId 和 currentSubHeadingId 存储在 localStorage 中,但问题仍然存在。如何确保页面刷新后加载正确的主题?
如有任何建议或解决方案,我们将不胜感激!
export const CourseSection = () => {
const [isSidebarOpen, setSidebarOpen] = useState(false);
const toggleSidebar = () => {
setSidebarOpen((prev) => !prev);
};
const params = useParams();
const { data: AllSubject } = useGetAllSubjectsQuery();
const { data: allSubheading } = useGetAllSubjectSubHeadingQuery();
const { data: allTopics } = useGetAllTopicHeadingsQuery();
const { data: allTopicContent } = useGetAllTopicContentsQuery();
const { data: allTopicHeadingImage } = useGetTopicImagesQuery();
const { data: allTopicCodeSnippet } = useGetAllTopicCodeSnippetQuery();
const { data: allTopicNotes } = useGetAllNotesQuery();
const [headings, setHeadings] = useState([]);
const [currentHeadingId, setCurrentHeadingId] = useState(localStorage.getItem("currentHeadingId") || null);
const [currentSubHeadingId, setCurrentSubHeadingId] = useState(localStorage.getItem("currentSubHeadingId") || null);
useEffect(() => {
if (AllSubject && allSubheading && allTopics && AllSubject.data && allSubheading.data && allTopics.data) {
const processedHeadings = AllSubject && AllSubject.data.filter((sub) => sub.id == params.tid).map((subject) => ({
...subject,
headings: allSubheading.data.filter((heading) => heading.subjectId === subject.id).map((heading) => ({
...heading,
subHeadings: allTopics.data.filter((topic) => topic.subHeadingId === heading.id),
})),
}));
setHeadings(processedHeadings);
if (processedHeadings.length > 0 && processedHeadings[0].headings.length > 0) {
setCurrentHeadingId(processedHeadings[0].headings[0].id);
localStorage.setItem("currentHeadingId", processedHeadings[0].headings[0].id)
setCurrentSubHeadingId(processedHeadings[0].headings[0].subHeadings[0].id);
localStorage.setItem("currentSubHeadingId", processedHeadings[0].headings[0].subHeadings[0].id)
} else {
setCurrentHeadingId(localStorage.getItem("currentHeadingId"))
setCurrentSubHeadingId(localStorage.getItem("currentSubHeadingId"))
}
}
}, [AllSubject, allSubheading, allTopics]);
const dispatch = useDispatch();
const course_selector = useSelector(state => state.course.all_contents);
useEffect(() => {
dispatch(get_all_contents({ topic_id: params.cid, AllSubject, allTopics, allTopicContent, allTopicHeadingImage, allTopicCodeSnippet, allTopicNotes }))
}, [params, AllSubject, allTopics, allTopicContent, allTopicHeadingImage, allTopicCodeSnippet, allTopicNotes]);
const getContentForCurrentSubHeading = () => {
const currentAnswer = allTopicContent && allTopicContent.data?.find((ans) => ans.topicHeadingId === currentSubHeadingId);
const currentPhoto = allTopicHeadingImage && allTopicHeadingImage.data?.find((img) => img.topicHeadingId === currentSubHeadingId);
const currentCodeSnippet = allTopicCodeSnippet && allTopicCodeSnippet.data?.find((cs) => cs.topicHeadingId === currentSubHeadingId);
const currentNotes = allTopicNotes && allTopicNotes.data?.find((note) => note.topicHeadingId === currentSubHeadingId);
const currentSubHeading = allTopics && allTopics.data?.find((sub) => sub.id === currentSubHeadingId);
const content = course_selector && course_selector.filter((content) => content.topicHeadingId === currentSubHeadingId)
return {
title: currentSubHeading ? currentSubHeading.topicHeadingName : '',
contents: content
};
};
const selectSubHeading = (headingId, subHeadingId) => {
setCurrentHeadingId(headingId);
setCurrentSubHeadingId(subHeadingId);
};
const handlePrev = () => {
const currentHeading = headings.flatMap(sub => sub.headings).find((h) => h.id === currentHeadingId);
const subHeadings = currentHeading ? currentHeading.subHeadings : [];
const currentIndex = subHeadings.findIndex((sub) => sub.id === currentSubHeadingId);
if (currentIndex > 0) {
setCurrentSubHeadingId(subHeadings[currentIndex - 1].id);
} else {
const prevHeadingIndex = headings.flatMap(sub => sub.headings).findIndex((h) => h.id === currentHeadingId) - 1;
if (prevHeadingIndex >= 0) {
const prevHeading = headings.flatMap(sub => sub.headings)[prevHeadingIndex];
setCurrentHeadingId(prevHeading.id);
setCurrentSubHeadingId(prevHeading.subHeadings[prevHeading.subHeadings.length - 1].id);
}
}
};
const handleNext = () => {
const currentHeading = headings.flatMap(sub => sub.headings).find((h) => h.id === currentHeadingId);
const subHeadings = currentHeading ? currentHeading.subHeadings : [];
const currentIndex = subHeadings.findIndex((sub) => sub.id === currentSubHeadingId);
if (currentIndex < subHeadings.length - 1) {
setCurrentSubHeadingId(subHeadings[currentIndex + 1].id);
} else {
const nextHeadingIndex = headings.flatMap(sub => sub.headings).findIndex((h) => h.id === currentHeadingId) + 1;
if (nextHeadingIndex < headings.flatMap(sub => sub.headings).length) {
const nextHeading = headings.flatMap(sub => sub.headings)[nextHeadingIndex];
setCurrentHeadingId(nextHeading.id);
setCurrentSubHeadingId(nextHeading.subHeadings[0].id);
}
}
};
const content = getContentForCurrentSubHeading();
// console.log(content)
return (
<div className="flex h-screen">
<Sidebar headings={headings && headings.length > 0 && headings} selectSubHeading={selectSubHeading} />
<MainContent content={content} handlePrev={handlePrev} handleNext={handleNext} />
</div>
);
};
在主题之间导航时,我尝试将 **currentHeadingId ** 和 **currentSubHeadingId ** 存储在 **localStorage ** 中。在页面加载时,我希望从 localStorage 检索这些值并将正确的主题设置为活动状态。然而,尽管实现了这种方法,页面在刷新时仍然重置为第一个主题,而不是加载预期的主题。
您可以将当前页面存储在 URL 查询参数中,而不是本地存储,这是处理此类缓存的常见方法和最佳实践。 基于 URL 查询参数,您可以轻松检索 currentHeadingId 或 currentSubHeadingId 等值。 https://v5.reactrouter.com/web/example/query-parameters