---
id: add-show-page
title: 3. Adding Show Page
tutorial:
  order: 0
  prev: 3.xx.xx/tutorial/adding-crud-pages/{preferredUI}/add-edit-page
  next: 3.xx.xx/tutorial/adding-crud-pages/{preferredUI}/add-create-page
---

Show page is the page where you can see the record. In this tutorial, we will create the show page for the `blog_posts` resource.

## Creating Show Page

First, let's create our file under the `src/pages/blog-posts` folder. We will name it `show.tsx`. Then, we will copy the show page code generated by Inferencer and paste it into the file.

To copy the code and paste it into the file, follow the steps below:

1. Navigate to the <a href="http://localhost:3000/blog-posts" rel="noopener noreferrer nofollow">localhost:3000/blog-posts</a> in your browser.

2. To open the show page, click any "Show" button in the "Actions" column of the table.

3. On the show page, click on the "Show Code" button in the bottom right corner of the page.

4. You can see the show page code generated by Inferencer. Click on the "Copy" button to copy the code.

5. Paste the code into the you created, `show.tsx` file.

You can see the show page code generated by Inferencer below:

```tsx live previewOnly previewHeight=600px url=http://localhost:3000/blog-posts/show/123
setInitialRoutes(["/blog-posts/show/123"]);

import { Refine } from "@pankod/refine-core";
import routerProvider from "@pankod/refine-react-router-v6";
import dataProvider from "@pankod/refine-simple-rest";
import { HeadlessInferencer } from "@pankod/refine-inferencer/headless";

const App = () => {
  return (
    <Refine
      routerProvider={routerProvider}
      dataProvider={dataProvider("https://api.fake-rest.refine.dev")}
      resources={[
        {
          name: "blog_posts",
          list: HeadlessInferencer,
          show: HeadlessInferencer,
          create: HeadlessInferencer,
          edit: HeadlessInferencer,
        },
      ]}
    />
  );
};
render(<App />);
```

Instead of coding the show page component from scratch, Inferencer created the required code base on API response, so that we can customize.

## Understanding the Show Component

We will go through the list page hooks one by one.

- `useShow` is a **refine** hook that is used to get single record data by using the `id` in the URL. It sends the parameters to the `dataProvider`'s `getOne` function and returns the result.

  [Refer to the `useShow` documentation for more information &#8594](/docs/3.xx.xx/api-reference/core/hooks/show/useShow/)

- `useNavigation` is a **refine** hook that is used to navigate between pages. In this case, we are using it to navigate to the `edit` and `list` pages when the user clicks on the "Edit" and "Blog Posts List" buttons.

  [Refer to the `useNavigation` documentation for more information &#8594](/docs/3.xx.xx/api-reference/core/hooks/navigation/useNavigation/)

- `useResource` is a **refine** hook that is used to get current resource information and `resources` that are defined on the `<Refine/>`.

  [Refer to the `useResource` documentation for more information &#8594](/docs/3.xx.xx/api-reference/core/hooks/resource/useResource/)

### Handling Relationships

In the show page, we have a single record. The record may have relationships with other resources.

For example, the `blog_posts` resource has a relationship with the `categories` resource. In this case, we can use the `useOne` hook provided by **refine**. This hook allows us to fetch single record data by using the `id` and `resource` parameters.

[Refer to the `useOne` documentation for more information &#8594](/docs/3.xx.xx/api-reference/core/hooks/data/useOne/)

In the auto-generated show page code, Inferencer used the `useOne` hook to fetch the category data of the blog post record.

```tsx
const { data: categoryData, isLoading: categoryIsLoading } = useOne({
  resource: "categories",
  id: record?.category?.id || "",
});
```

To ensure that the related data is only fetched after the blog post record has been successfully retrieved, we can use the `queryOptions` object. By setting the `enabled` property to `true` only if the record variable is truthy, we can control when the related data is fetched like below:

```tsx
const { data: categoryData, isLoading: categoryIsLoading } = useOne({
  resource: "categories",
  id: record?.category?.id || "",
  queryOptions: {
    enabled: !!record,
  },
});
```

## Adding the Show Page to the App

Now that we have created the show page, we need to add it to the `App.tsx` file.

1. Open `src/App.tsx` file on your editor.

2. Import the created `BlogPostShow` component.

3. Replace the `HeadlessInferencer` component with the `BlogPostShow` component.

```tsx title="src/App.tsx"
import { Refine } from "@pankod/refine-core";
import routerProvider from "@pankod/refine-react-router-v6";
import dataProvider from "@pankod/refine-simple-rest";
import { HeadlessInferencer } from "@pankod/refine-inferencer/headless";

import { BlogPostList } from "pages/blog-posts/list";
import { BlogPostEdit } from "pages/blog-posts/edit";
//highlight-next-line
import { BlogPostShow } from "pages/blog-posts/show";

const App = () => {
  return (
    <Refine
      routerProvider={routerProvider}
      dataProvider={dataProvider("https://api.fake-rest.refine.dev")}
      resources={[
        {
          name: "blog_posts",
          list: BlogPostList,
          edit: BlogPostEdit,
          //highlight-next-line
          show: BlogPostShow,
          create: HeadlessInferencer,
        },
      ]}
    />
  );
};
export default App;
```

Now, we can see the show page in the browser at <a href="http://localhost:3000/blog-posts/show/123" rel="noopener noreferrer nofollow">localhost:3000/blog-posts/show/123</a>

<br/>
<br/>

<Checklist>

<ChecklistItem id="add-show-page-headless">
I added the show page to the app.
</ChecklistItem>
<ChecklistItem id="add-show-page-headless-2">
I understood the show page components and hooks.
</ChecklistItem>
<ChecklistItem id="add-show-page-headless-3">
I understood the relationship handling.
</ChecklistItem>

</Checklist>
