Adding PageTemplate and Redux support to Storybook
Let's add the page templates to Storybook.
Before jumping into the page components, first let's check a component that is present at every page: the PageTemplate
.
What's a page template anyway?#
It's quite common to have a page wrapper that handles things like navigation, state management, and other functionality, while also displaying the page content under different layout settings that include components like Header and Footer. In MealDrop, every page is rendered under a page template, used in three different layouts:
1 - Default
This template is the most common. It wraps the page with the Header
and Footer
components. The Header
is a connected component that gets shopping cart data from Redux and provides navigation items to other pages. It is used in pages like HomePage
, CategoryPage
and CategoryDetailPage
.
2 - Sticky Header
This template is almost the same as Default, but with a sticky header, so that the shopping cart button is visible even when scrolling the page. It is used in the RestaurantDetailPage
.
3 - Basic
This template is the simplest version possible, only including a non-connected version of the Header
component, with no navigation. It is used in the CheckoutPage
and SuccessPage
.
Adding the component to Storybook#
It's pretty useful having a way to visualize all available page templates in one place. Let's add that to Storybook!
The PageTemplate
component receives children
as props, as well as layout
:
type PageTemplateProps = {
layout?: 'default' | 'sticky-header' | 'basic'
}
We start by running Storybook and creating the boilerplate for src/templates/PageTemplate.stories.tsx
. Let's also create a DummyComponent
to serve as children of the template, just to add some text and make the story more understandable for the ones who will access it.
// src/templates/PageTemplate.stories.tsx
import * as React from 'react'
import { ComponentMeta, ComponentStory } from '@storybook/react'
import { PageTemplate } from './PageTemplate'
export default {
title: 'Templates/PageTemplate',
component: PageTemplate
} as ComponentMeta<typeof PageTemplate>
// Just to make the story a bit more understandable for the users
const DummyComponent: React.FC = ({ children }) => <div style={{ padding: 60 }}>{children}</div>
const Template: ComponentStory<typeof PageTemplate> = (args) => <PageTemplate {args} />
export const Default = Template.bind({})
Default.args = {
children: (
<DummyComponent>
Default template with scrollable header and navigation items + Footer
</DummyComponent>
),
}
When checking the story on Storybook, we see an error: could not find react-redux context value; please ensure the component is wrapped in a Provider:

What should we do? The error is quite descriptive, and once again, sounds like we can fix that by creating a decorator.
Adding Redux support#
Adding Redux support to Storybook is rather a straightforward process. We need to create a decorator that wraps a story in a Redux provider with our real store, which comes from src/app-state/index.ts
. Let's open the decorators
file and add a new decorator called withStore
:
// .storybook/decorators.tsx
// ... other imports
import { Provider as StoreProvider } from 'react-redux'
import { store } from '../src/app-state'
// ... other decorators here
export const withStore: DecoratorFn = (StoryFn) => {
return (
<StoreProvider store={store}>
<StoryFn />
</StoreProvider>
)
}
export const globalDecorators = [
//... the other decorators,
withStore
]
When accessing our story, we notice that the error went away and we now have a page template with a header and a footer!

This page is a preview of Storybook for React Apps