You have several options:
1. Fetch the page if the home has been loaded
This can be a good option if you don’t need server-side rendering for that page. It is also much simpler than creating a new handler (shown later):
const Theme = ({ state, actions }) => {
// ...
React.useEffect(() => {
if (state.router.link === "/")
actions.source.fetch("/bio");
}, [state.router.link]);
// ...
};
Then, you can wait until the bio page data is ready to show the items:
const Home = ({ state }) => {
const data = state.source.get("/");
const bioData = state.source.get("/bio");
return (
bioData.isReady &&
<>
<Items items={data.items} />
<BioPage />
</>
);
};
Or show them independently:
const Home = ({ state }) => {
const data = state.source.get("/");
const bioData = state.source.get("/bio");
return (
<>
<Items items={data.items} />
{bioData.isReady ? <BioPage /> : <Loading />}
</>
);
};
2. Fetch the page when the home loads but add server-side rendering
This is similar to the previous one, but with the added benefit of adding server-side rendering.
The Theme
and Home
components are the same than in the previous one, but you also add a new beforeSSR
action:
export default {
roots: { /* ... */ },
state: { /* ... */ },
actions: {
theme: {
beforeSSR: async ({ state, actions }) => {
if (state.router.link === "/") {
// Stop the server-side rendering (SSR) until this is ready.
await actions.source.fetch("/bio");
}
}
}
}
}
This way, if we are doing a server-side rendering of the home page, we make sure the bio page is also in the state.
3. Overwrite the home handler with the new page
This is the most complex one, but it’s another option. The only benefit is that once data.isReady
you are sure that the bio page is also ready. You don’t need to check for bioData.isReady
in the Home
component.
const homeHandler = {
name: "home",
priority: 10,
pattern: "/",
func: async ({ route, state, libraries }) => {
const { api } = libraries.source;
const { page, query } = parse(route);
// 1. Fetch the specified pages.
const homePromise = api.get({
endpoint: "posts",
params: { search: query.s, page, _embed: true, ...state.source.params }
});
const bioPromise = api.get({
endpoint: "pages",
params: { slug: "bio", _embed: true }
});
const [homeResponse, bioResponse] = await Promise.all([
homePromise,
bioPromise
]);
// 2. Populate the state.
const items = await populate({ response: homeResponse, state });
await populate({ response: bioResponse });
if (page > 1 && items.length === 0)
throw new Error(`post archive doesn't have page ${page}`);
// 3. get posts and pages count
const total = getTotal(response);
const totalPages = getTotalPages(response);
// 4. Add data to source.
Object.assign(state.source.data[route], {
items,
total,
totalPages,
isArchive: true,
isPostTypeArchive: true,
isHome: true
});
}
};
Then, access the bio data in the <Home>
component:
const Home = ({ state }) => {
const data = state.source.get("/");
const bioData = state.source.get("/bio");
// both data and bioData are ready...
};