React 中页面刷新时保留当前主题的问题

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

我正在使用 React 构建一个编程教程网站。每个内容页面都有一个侧边栏和一个主要内容部分,其中包含用于导航主题的“上一个”和“下一个”按钮。但是,当我在查看特定主题(例如第 10 个主题)时刷新页面时,它会重置为第一个主题,而不是停留在当前主题。

为了解决此问题,我将 currentHeadingIdcurrentSubHeadingId 存储在 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 检索这些值并将正确的主题设置为活动状态。然而,尽管实现了这种方法,页面在刷新时仍然重置为第一个主题,而不是加载预期的主题。

reactjs frontend navigation local-storage react-state-management
1个回答
0
投票

您可以将当前页面存储在 URL 查询参数中,而不是本地存储,这是处理此类缓存的常见方法和最佳实践。 基于 URL 查询参数,您可以轻松检索 currentHeadingId 或 currentSubHeadingId 等值。 https://v5.reactrouter.com/web/example/query-parameters

© www.soinside.com 2019 - 2024. All rights reserved.