Frontend Serverless with React and GraphQL
Start at the beginning and work your way through this project. The code for each step as well as the finished project can be found in the Github repository.
17. Add Recipe page
Objective: Create the page that we will use for single recipe pages.
Now that we have a working Recipes Page, let's create the single Recipe Page. We will get here by clicking on a Recipe card from the Recipes Page. Next.js 9 has a feature where you can do limited routing based on how files are stored in the pages directory. Here are a few rules:
A file called recipe.tsx
in the root of the pages directory will create a route at /recipe
.
A file called index.tsx
in the pages/recipe
folder will also create a route at /recipe
.
A file called [id].tsx
in the pages/recipe
folder will create a dynamic route where it will feed the id like this /recipe/:id
in the path and it will create a paramter called id
that it will passs as an initialProps into the component in the [id].tsx
file. We will use this feature below:
pages/recipe/[id].tsx
import { useQuery } from '@apollo/react-hooks';import { recipeGraphQL } from '../../graphql/queries/recipe';import * as _ from 'lodash';import { Loading } from '../../components/notify/Loading';import { MainLayout } from '../../components/layout/MainLayout';import { Error } from '../../components/notify/Error';const Recipe = ({ id }) => {const { loading, data, error } = useQuery(recipeGraphQL, {variables: { where: { id } },});const title = _.get(data, 'recipe.title');if (loading) {return (<MainLayout title="Recipe Loading"><Loading /></MainLayout>);}if (error) {return (<MainLayout title="Recipe Loading Error"><Error errorText={`${error}`} /></MainLayout>);}if (!title) {return (<MainLayout title="Not a valid recipe"><Error errorText={`Not a valid recipe`} /></MainLayout>);}return (<MainLayout title={title}><p>{title}</p></MainLayout>);};Recipe.getInitialProps = ({ query }) => {const { id } = query;return { id };};export default Recipe;
We can use this parameter feature from naming the file [id].tsx
to pass the id into our Recipe component. We then will run a query for a recipe based on that id and we can render different MainLayout's based on what condition the component is under. We are using the <MainLayout>
so that we an appropriately label the title in the head of the document appropriately.
In the case where everything is loaded, for now we simply display the recipe title. We will expand this out later to actually add our recipe, but this is a good start.