mirror of
https://github.com/wgh136/nysoure.git
synced 2025-09-27 12:17:24 +00:00
add AppContext for state management and update ResourcesView to utilize context
This commit is contained in:
19
frontend/src/components/AppContext.tsx
Normal file
19
frontend/src/components/AppContext.tsx
Normal 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)
|
||||||
|
}
|
@@ -4,12 +4,38 @@ import showToast from "./toast.ts";
|
|||||||
import ResourceCard from "./resource_card.tsx";
|
import ResourceCard from "./resource_card.tsx";
|
||||||
import {Masonry, useInfiniteLoader} from "masonic";
|
import {Masonry, useInfiniteLoader} from "masonic";
|
||||||
import Loading from "./loading.tsx";
|
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 [data, setData] = useState<Resource[]>([])
|
||||||
const pageRef = useRef(1)
|
const pageRef = useRef(1)
|
||||||
const totalPagesRef = useRef(1)
|
const totalPagesRef = useRef(1)
|
||||||
const isLoadingRef = useRef(false)
|
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 () => {
|
const loadPage = useCallback(async () => {
|
||||||
if (pageRef.current > totalPagesRef.current) return
|
if (pageRef.current > totalPagesRef.current) return
|
||||||
|
@@ -6,6 +6,7 @@ import i18n from "i18next";
|
|||||||
import {initReactI18next} from "react-i18next";
|
import {initReactI18next} from "react-i18next";
|
||||||
import LanguageDetector from "i18next-browser-languagedetector";
|
import LanguageDetector from "i18next-browser-languagedetector";
|
||||||
import {i18nData} from "./i18n.ts";
|
import {i18nData} from "./i18n.ts";
|
||||||
|
import AppContext from "./components/AppContext.tsx";
|
||||||
|
|
||||||
i18n
|
i18n
|
||||||
.use(initReactI18next)
|
.use(initReactI18next)
|
||||||
@@ -20,7 +21,9 @@ i18n
|
|||||||
}).then(() => {
|
}).then(() => {
|
||||||
createRoot(document.getElementById('root')!).render(
|
createRoot(document.getElementById('root')!).render(
|
||||||
<StrictMode>
|
<StrictMode>
|
||||||
<App/>
|
<AppContext>
|
||||||
|
<App/>
|
||||||
|
</AppContext>
|
||||||
</StrictMode>,
|
</StrictMode>,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@@ -32,6 +32,6 @@ export default function HomePage() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
<ResourcesView loader={(page) => network.getResources(page)}></ResourcesView>
|
<ResourcesView storageKey={"home_page"} loader={(page) => network.getResources(page)}></ResourcesView>
|
||||||
</>
|
</>
|
||||||
}
|
}
|
@@ -232,7 +232,7 @@ function Article({ resource }: { resource: ResourceDetails }) {
|
|||||||
if (!resource.related) {
|
if (!resource.related) {
|
||||||
return;
|
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") {
|
if (child.tagName === "P" && child.children.length === 1 && child.children[0].tagName === "A") {
|
||||||
const href = (child.children[0] as HTMLAnchorElement).href as string
|
const href = (child.children[0] as HTMLAnchorElement).href as string
|
||||||
if (href.startsWith(window.location.origin) || href.startsWith("/")) {
|
if (href.startsWith(window.location.origin) || href.startsWith("/")) {
|
||||||
@@ -279,7 +279,7 @@ function Article({ resource }: { resource: ResourceDetails }) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [resource])
|
}, [navigate, resource])
|
||||||
|
|
||||||
return <article ref={articleRef}>
|
return <article ref={articleRef}>
|
||||||
<Markdown>{resource.article}</Markdown>
|
<Markdown>{resource.article}</Markdown>
|
||||||
|
Reference in New Issue
Block a user