Skip to content

Commit

Permalink
feat: refetch page data when pathname change in spa mode
Browse files Browse the repository at this point in the history
  • Loading branch information
sanyuan0704 committed Sep 17, 2022
1 parent d2e978c commit 2bc4b41
Show file tree
Hide file tree
Showing 6 changed files with 35 additions and 21 deletions.
20 changes: 13 additions & 7 deletions src/client/runtime/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ import { Route } from '../../node/plugin-routes';
import { omit } from './utils';
import { PageData } from '../../shared/types';
import { HelmetProvider } from 'react-helmet-async';
import { useEffect } from 'react';
import { useContext, useEffect, useLayoutEffect } from 'react';
import { DataContext, useSetPageData } from './hooks';

export async function waitForApp(path: string): Promise<PageData> {
const matched = matchRoutes(routes, path)!;
if (matched) {
// Preload route component
const mod = await (matched[0].route as Route).preload();
console.log(mod);
return {
siteData,
pagePath: (matched[0].route as Route).filePath,
Expand All @@ -29,19 +29,25 @@ export async function waitForApp(path: string): Promise<PageData> {
}

export function App({
helmetContext,
setPageData
helmetContext
}: {
helmetContext?: object;
setPageData?: React.Dispatch<React.SetStateAction<PageData>>;
}) {
const { pathname } = useLocation();
useEffect(() => {
const setPageData = useContext(DataContext).setData;

useLayoutEffect(() => {
async function refetchData() {
setPageData && setPageData(await waitForApp(pathname));
const pageData = await waitForApp(pathname);
try {
setPageData(pageData);
} catch (e) {
console.log(e);
}
}
refetchData();
}, [pathname]);
}, [pathname, setPageData]);

return (
<HelmetProvider context={helmetContext}>
Expand Down
7 changes: 3 additions & 4 deletions src/client/runtime/client-entry.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,12 @@ async function renderInBrowser() {
const enhancedApp = async () => {
const { waitForApp, App } = await import('./app');
const initialPageData = await waitForApp(window.location.pathname);
return () => {
return function RootApp() {
const [pageData, setPageData] = useState(initialPageData);

return (
<DataContext.Provider value={pageData}>
<DataContext.Provider value={{ data: pageData, setData: setPageData }}>
<BrowserRouter>
<App setPageData={setPageData} />
<App />
</BrowserRouter>
</DataContext.Provider>
);
Expand Down
17 changes: 13 additions & 4 deletions src/client/runtime/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,19 @@ import { createContext, useContext } from 'react';
import { PageData } from '../../shared/types';
import { inBrowser } from './utils';

export const DataContext = createContext(
inBrowser() ? window?.ISLAND_PAGE_DATA : null
);
export const DataContext = createContext({
data: inBrowser() ? window?.ISLAND_PAGE_DATA : null,
setData: (_data: PageData) => {}
});

export const usePageData = () => {
return useContext(DataContext) as PageData;
return useContext(DataContext).data as PageData;
};

export const useSetPageData = (data: PageData) => {
try {
return useContext(DataContext).setData(data);
} catch (e) {
console.log(e);
}
};
1 change: 0 additions & 1 deletion src/client/runtime/island-jsx-runtime.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,4 @@ export const jsx = (...args) => internalJsx(originJsx, ...args);

export const jsxs = (...args) => internalJsx(originJsxs, ...args);

//@ts-ignore
export const Fragment = jsxRuntime.Fragment;
9 changes: 5 additions & 4 deletions src/client/runtime/sideEffects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ const DEFAULT_NAV_HEIGHT = 72;

// Control the scroll behavior of the browser when user clicks on a link
if (inBrowser()) {
function scrollTo(el: HTMLElement, hash: string, smooth = false) {
// eslint-disable-next-line no-inner-declarations
function scrollTo(el: HTMLElement, hash: string, isSmooth = false) {
let target: HTMLElement | null = null;
try {
target = el.classList.contains('header-anchor')
Expand All @@ -26,11 +27,11 @@ if (inBrowser()) {
target.getBoundingClientRect().top -
DEFAULT_NAV_HEIGHT +
targetPadding;

// Only scroll smoothly in page header anchor
window.scrollTo({
left: 0,
top: targetTop,
behavior: 'smooth'
...(isSmooth ? { behavior: 'smooth' } : {})
});
}
}
Expand All @@ -44,7 +45,7 @@ if (inBrowser()) {
const { origin, hash, target } = link;
const currentUrl = window.location;
// only intercept inbound links
if (hash && target !== `_blank` && origin === currentUrl.origin) {
if (hash && target !== '_blank' && origin === currentUrl.origin) {
e.preventDefault();
// scroll between hash anchors in the same page
if (hash && hash !== currentUrl.hash) {
Expand Down
2 changes: 1 addition & 1 deletion src/client/runtime/ssr-entry.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export async function render(
data.islandProps = [];
data.islandToPathMap = {};
const appHtml = renderToString(
<DataContext.Provider value={pageData}>
<DataContext.Provider value={{ data: pageData, setData: () => {} }}>
<StaticRouter location={pagePath}>
<App helmetContext={helmetContext} />
</StaticRouter>
Expand Down

0 comments on commit 2bc4b41

Please sign in to comment.