- What is a Custom Template?
- What is React?
- The Approach
- Procedure
- Prerequisites
- Install Dependencies
- Configure Webpack
- Optional: Add CSS loader
- Create custom template
- Map the Custom Template in .stencil
- Test the Custom Template
- Create a custom module
- Map the Custom Module to the Custom Template
- Finally the Result
If you wish to incorporate React into your Stencil theme, there are a few reasons one may want to do so. You may want to utilize an existing component library in React or it may be your preferred front-end framework. In some cases, projects of this nature take a headless approach where the website’s front-end exists separately from BigCommerce and integrates with BigCommerce APIs to manage catalog data, customer accounts, promotions, carts, and checkout processes. Other times, React is combined with Stencil so that BigCommerce hosts the front end.
I have observed a few methods for including React in a Stencil theme, each with its own advantages and disadvantages. This article aims to provide a step-by-step guide to starting custom templates with React in a Stencil theme in a scalable and reusable manner.
What is a Custom Template?
All pages of the same type use the same template file in a Stencil theme by default. Examples of page types are product detail pages, category pages which list products, brand pages which list products, and web pages which are content pages.
You can make a custom template for some pages of the same type. For example, if a store needs a different layout for some category pages to show info from outside, the store can use custom templates from the Stencil theme for those categories. This article shows how to make a custom template for a category page that shows page details in a React part.
What is React?
React
is a very popular front-end framework today. It lets developers make pieces of a website (components) that have their own data and can work together to build complex user interfaces. There are lots of React tutorials and examples online, so I won’t explain it much here.
This article is for developers already familiar with basic React concepts. In this article, I will show how to make a React component that gets context data from Stencil about the category page. This context data includes things like the products that should be shown.
The Approach
In this example, we can make use of a technique developed by sacr3dc0w to connect a personalized template, with a custom JavaScript module. In this scenario, the module expands on the PageManager class. Utilizes its onReady function to display React within an element in the personalized template.
The personalized template retrieves information from Stencil using Handlebars. Inserts it into a variable called “context” which can then be accessed by the JavaScript module through the PageManager constructor. Subsequently, the JavaScript module transfers the page context to React as a prop.
In the below example, the React component will simply display the text “Hello” followed by category data from the stencil.
Procedure
Prerequisites
-
Bigcommerce Store
If you do not already have a BigCommerce store, you can set up a trial at
https://www.bigcommerce.com/essentials/
-
Node and NPM
The Stencil CLI runs in the Node runtime environment. BigCommerce currently recommends Node version 18.15.0 and provides instructions to install the recommended version of Node here.
-
Stencil CLI
npm install -g @bigcommerce/stencil-cliFor more information on installing Stencil CLI, see the BigCommerce documentation.
-
Cornerstone Theme
You can use this approach in any Stencil theme, but this example will utilize the reference implementation called Cornerstone. It’s good to create a folder to store your Stencil themes, and clone Cornerstone or another theme for each new project. For this example, I will assume you are cloning Cornerstone into a folder named demo.
git clone https://github.com/bigcommerce/cornerstone demo
cd demo
npm install
After cloning the theme and installing base dependencies, initialize the theme with your store’s API credentials. Log into your BigCommerce store and navigate to Advanced Settings > API Accounts. Click Create API Account > Create Stencil-CLI Token. Copy the quickstart command, paste it into your terminal, and press enter three times. The command should be similar to:
stencil init –url https://<your-domain> –token <api-token>
For more information on cloning and initializing the Cornerstone theme see the BigCommerce documentation.
Install Dependencies
Add React, ReactDOM, and the React preset for Babel to your project.
npm install react react-dom @babel/preset-react
Configure Webpack
In webpack.common.js, add [‘@babel/preset-react’] to modules.rules[0].use.options.presets. This is the presets array from the example
presets: [
[‘@babel/preset-env’, {
loose: true,
modules: false,
useBuiltIns: ‘usage’,
targets: ‘> 1%, last 2 versions, Firefox ESR’,
}],
[‘@babel/preset-react’],
],
:
Optional: Add CSS loader
While adding CSS files is optional for this example, you may want to include CSS file loaders if you plan to add your own CSS files to the React app or use a component library that includes CSS modules such as React Toolbox. These steps have been tested when using React Toolbox.
1. Install Dependencies:
npm install style-loader css-loader
2. Add the following to the modules.rules array in webpack.common.js:
{
test: /\.css/,
loader:[ ‘style-loader’, ‘css-loader’ ]
}
Create custom template
This article will show how to make a custom category page template. You can also do this for product, brand, or web page templates. First, make a new folder called templates/custom/category.
- Windows:
mkdir templates\pages\custom\category
- Mac/Linux
mkdir templates/pages/custom/category
The resulting structure of the templates folder should be organized as follows:
templates
∟ components
∟ layout
∟ pages
…
∟ custom
∟ category
…
Copy templates\pages\category.html to the new folder and rename it demo.html:
- Windows:
copy templates\pages\category.html templates\pages\custom\category\demo.html
- Mac/Linux
cp templates/pages/category.html templates/custom/category/demo.html
In demo.html replace everything between {{#partial “page”}}and {{/partial}} with:
{{inject “category” category}}
<div id=”root”>Hello</div>
The {{inject}} helper adds the category object from Stencil to the page context your custom JavaScript module will be able to access.
The <div> will display “Hello” so you can test to validate the template mapping. It will also serve as the mounting point for React
—
category:
shop_by_price: true
products:
limit: {{theme_settings.categorypage_products_per_page}}
—
{{inject “categoryProductsPerPage” theme_settings.categorypage_products_per_page}}
{{#partial “head”}}
{{#if pagination.category.previous}}
<link rel=”prev” href=”{{pagination.category.previous}}”>
{{/if}}
{{#if pagination.category.next}}
<link rel=”next” href=”{{pagination.category.next}}”>
{{/if}}
{{/partial}}
{{#partial “page”}}
{{inject “category” category}}
<div id=”root”>Hello</div>
{{/partial}}
{{> layout/base}}
Map the Custom Template in .stencil
In the project’s .stencil file, you will map the custom page template file to a category page URL. This is so you can render your custom page template in your local environment. Once the theme is applied to a store, you will need to map specific categories to the template to use your custom template on the live site. For more on applying custom templates, see the BigCommerce documentation.
{
“normalStoreUrl”: “https://<store-domain>”,
“accessToken”: “<api-token>”,
“port”: 3000,
“customLayouts”: {
“brand”: {},
“category”: {
“demo.html”: “/demo/”
},
“page”: {},
“product”: {}
}
}
If you prefer to simply change the default template and apply your template with React to every category, you can make the same changes to the existing templates\pages\category.html and assets\js\theme\category.js files, then skip this mapping step.
Test the Custom Template
Confirm your template is mapped correctly by starting the local development server with Stencil CLI:
stencil start
Navigate to the mapped URL on localhost to ensure your template is rendered. For example: http://localhost:3000/demo/
You should see the global header and footer, and the text Hello in the main content area:
Create a custom module
The React app will live in assets\js\theme\custom\demo.js. Start by creating the folder.
- Windows:
mkdir assets\js\theme\custom
- Mac/Linux
mkdir assets/js/theme/customThen, create the file:
- Windows:
You can use File Explorer or try using PowerShell.
- Mac/Linux
touch assets/js/theme/custom/demo.js
In demo.js, import React, ReactDOM, and PageManager:
import React from ‘react’
import ReactDOM from ‘react-dom’
import PageManager from ‘../page-manager’
In demo.js, create a simple Hello component that displays its props:
const Hello = (props) => (
<div>
<p>Hello from React!</p>
<p>Here are my props:</p>
<pre>{JSON.stringify(props, null, 2)}</pre>
</div>
)
In demo.js, export a new child class that extends the PageManager class. This class is responsible for mounting the Hello component in the div in the custom category template, and passing the page context to the component as a prop:
export default class Demo extends PageManager {
onReady() {
const container = $(‘#root’)[0]
ReactDOM.render(<Hello context={this.context}/>, container)
}
}
See the whole code below…
import React from ‘react’
import ReactDOM from ‘react-dom’
import PageManager from ‘../page-manager’
const Hello = (props) => (
<div>
<p>Hello from React!</p>
<p>Here are my props:</p>
<pre>{JSON.stringify(props, null, 2)}</pre>
</div>
)
export default class Demo extends PageManager {
onReady() {
const container = $(‘#root’)[0]
ReactDOM.render(<Hello context={this.context}/>, container)
}
}
Map the Custom Module to the Custom Template
We need to load our module on the pages that render the custom template to add a mapping to the customClasses object in assets\js\app.js. Since the value of context.templatein app.js may vary depending on the environment, the example maps the module to the value provided by both Windows and Mac/Linux environments:
const customClasses = {
‘pages\\custom\\category\\demo’: () => import(‘./theme/custom/demo’), // Windows
‘pages/custom/category/demo’: () => import(‘./theme/custom/demo’), // Mac/Linux
};
Finally the Result
When you visit the category page on your local website, you should now see a custom template displaying React components. This template has access to category page data provided by Stencil.
The product listing page uses context.category to include information needed from Stencil. You can use {{inject}} in templates\pages\custom\category\demo.html to add more context to the page. Or follow the same pattern to include custom React modules on product, brand, and other pages.
About Author
Dipak Patil - Delivery Head & Partner Manager
Dipak is known for his ability to seamlessly manage and deliver top-notch projects. With a strong emphasis on quality and customer satisfaction, he has built a reputation for fostering strong client relationships. His leadership and dedication have been instrumental in guiding teams towards success, ensuring timely and effective delivery of services.