Creating a Page
This tutorial was contributed by Sai Charan and Tejas Dinkar
In this tutorial, we will create a new page for an author. With this example, we will demonstrate how a custom page can have its own logic of fetching respective data, and how to render a separate UI.
If you would like to know how this works in more detail, consider reading the Server Side Architecture document.
Creating a pageType
The first step of any new page is to create a pageType for the page to be rendered.
In app/isomorphic/constants.js, we add the new constant
export const PAGE_TYPE = Object.freeze({
...
AUTHOR_PAGE: "author-page",
...
});
Building a custom page
We first need to add a respective route for it in app/server/routes.js. Since the author page is not a static page, we put it under ISOMORPHIC_ROUTES, which is later exported by generateRoutes.
In app/server/routes.js, we add the following line:
const ISOMORPHIC_ROUTES = [
...
{ path: "/author/:authorId", pageType: PAGE_TYPE.AUTHOR_PAGE, exact: true },
...
];
On the route /author/:authorId
, the pageType will be set to PAGE_TYPE.AUTHOR_PAGE
Loading the data
We next set up the data required for our page. We do this in app/server/load-data.js.
In app/server/load-data.js, we modify the loadData function to add the case which invokes the particular function call depending on the page.
Example, in app/server/load-data.js, we add the following
import { loadAuthorPageData } from "./data-loaders/author-page-data";
export function loadData(pageType, params, config, client, { host, next, domainSlug, cookies }) {
function _loadData() {
switch (pageType) {
...
case PAGE_TYPE.AUTHOR_PAGE:
return loadAuthorPageData(client, params.authorId, config);
...
}
}
Note: Getting cookies in load data, the publisher needs to install cookies parser middleware and use it in FE app.
Example, in app/server/app.js, add the following
var cookieParser = require("cookie-parser");
app.use(cookieParser());
We need to add a file in app/server/data-loaders called *author-page-data.js where we make an api call to get the respective author data.
import { Author } from "@quintype/framework/server/api-client";
import { storyToCacheKey } from "@quintype/framework/server/caching";
export function loadAuthorPageData(client, authorId, config) {
const params = {
"item-type": "story",
limit: 10,
offset: 0
};
const authorStories = Author.getAuthorCollection(client, authorId, params).then(({ items }) =>
items.map(({ story }) => story)
);
const author = Author.getAuthor(client, authorId);
return Promise.all([author, authorStories])
.then(([author, stories]) => {
return {
author: author.asJson(),
stories,
cacheKeys: stories.map(story => storyToCacheKey(config["publisher-id"], story))
};
})
.catch(error => {
console.log("in error", error);
});
}
So now that we have created a route, and loaded the data, all we need to do is to start rendering.
Picking the component
Once the data is loaded, we are now ready to pick a component and render the UI.
In our example, we add the following.
import { PAGE_TYPE } from "./constants";
import { pickComponentHelper } from "@quintype/framework/server/pick-component-helper";
const { pickComponent, getChunkName } = pickComponentHelper(
{
...
[PAGE_TYPE.AUTHOR_PAGE]: { chunk: "list", component: "AuthorPage" }
...
}
);
export { pickComponent, getChunkName };
A new file has to be created app/isomorphic/components/pages/author.js where it contains the AuthorPage component exported.
The file, app/isomorphic/components/pages/author.js is where we have the component to render the AuthorPage.
import React from "react";
export function AuthorPage({ data }) {
const { author, stories } = data;
return (
<div>
<p>Author name is {author.name}, they have written the following stories:</p>
<ul>
{stories.map(story => (
<li><a href={story.url}>{story.headline}</a></li>
))}
</ul>
</div>
);
}
And finally, we add the new component to app/isomorphic/component-bundles/list.js to be exported.
...
export { AuthorPage } from "../components/pages/author";
...
Seeing it all in action
Head over to http://localhost:3000/author/2038, and you should see something like the following
You may now proceed to Adding a Homepage Component or jump to a recipe from the Tutorial.