add AppContext for state management and update ResourcesView to utilize context

This commit is contained in:
2025-05-23 21:53:39 +08:00
parent 81053d56f7
commit 4038683a56
5 changed files with 53 additions and 5 deletions

View File

@@ -0,0 +1,19 @@
import {createContext, ReactNode, useContext} from "react";
export default function AppContext({
children,
}: {
children: ReactNode;
}) {
return (
<context.Provider value={new Map<string, any>()}>
{children}
</context.Provider>
);
}
const context = createContext<Map<string, any>>(new Map<string, any>());
export function useAppContext() {
return useContext(context)
}

View File

@@ -4,13 +4,39 @@ import showToast from "./toast.ts";
import ResourceCard from "./resource_card.tsx";
import {Masonry, useInfiniteLoader} from "masonic";
import Loading from "./loading.tsx";
import {useAppContext} from "./AppContext.tsx";
export default function ResourcesView({loader}: {loader: (page: number) => Promise<PageResponse<Resource>>}) {
export default function ResourcesView({loader, storageKey}: {loader: (page: number) => Promise<PageResponse<Resource>>, storageKey?: string}) {
const [data, setData] = useState<Resource[]>([])
const pageRef = useRef(1)
const totalPagesRef = useRef(1)
const isLoadingRef = useRef(false)
const appContext = useAppContext()
useEffect(() => {
if (storageKey) {
const data = appContext.get(storageKey + "/data")
const page = appContext.get(storageKey + "/page")
const totalPages = appContext.get(storageKey + "/totalPages")
console.log("loading data", data, page, totalPages)
if (data) {
setData(data)
pageRef.current = page
totalPagesRef.current = totalPages
}
}
}, [appContext, storageKey]);
useEffect(() => {
if (storageKey && data.length > 0) {
console.log("storing data", data)
appContext.set(storageKey + "/data", data)
appContext.set(storageKey + "/page", pageRef.current)
appContext.set(storageKey + "/totalPages", totalPagesRef.current)
}
}, [appContext, data, storageKey]);
const loadPage = useCallback(async () => {
if (pageRef.current > totalPagesRef.current) return
if (isLoadingRef.current) return

View File

@@ -6,6 +6,7 @@ import i18n from "i18next";
import {initReactI18next} from "react-i18next";
import LanguageDetector from "i18next-browser-languagedetector";
import {i18nData} from "./i18n.ts";
import AppContext from "./components/AppContext.tsx";
i18n
.use(initReactI18next)
@@ -20,7 +21,9 @@ i18n
}).then(() => {
createRoot(document.getElementById('root')!).render(
<StrictMode>
<App/>
<AppContext>
<App/>
</AppContext>
</StrictMode>,
)
})

View File

@@ -32,6 +32,6 @@ export default function HomePage() {
</div>
</div>
}
<ResourcesView loader={(page) => network.getResources(page)}></ResourcesView>
<ResourcesView storageKey={"home_page"} loader={(page) => network.getResources(page)}></ResourcesView>
</>
}

View File

@@ -232,7 +232,7 @@ function Article({ resource }: { resource: ResourceDetails }) {
if (!resource.related) {
return;
}
for (let child of articleRef.current.children) {
for (const child of articleRef.current.children) {
if (child.tagName === "P" && child.children.length === 1 && child.children[0].tagName === "A") {
const href = (child.children[0] as HTMLAnchorElement).href as string
if (href.startsWith(window.location.origin) || href.startsWith("/")) {
@@ -279,7 +279,7 @@ function Article({ resource }: { resource: ResourceDetails }) {
}
}
}
}, [resource])
}, [navigate, resource])
return <article ref={articleRef}>
<Markdown>{resource.article}</Markdown>