Skip to main content

A React Example in Sitecore

That's true, Sitecore components are useful and provide lots of facilities. They allow to build fully flexible website. And there is not much problem using post-backs to display your contents. However, if your website has user interactions, then it could be a headache. Too many post-backs would occur a poor user experience.

That's why client-side technologies are really powerful and popular for a long time. There are plenty of javascript libraries and frameworks which all try to provide better user experience in different ways.

It is not a topic of this article why I chose React. There are some good articles about it (e.g. Jonne Kats' great article). However, one of the reasons is React only focus on view part. It is not a fully framework like Angular, it is rich featured library instead. And that's what I was looking for! The idea was to benefit Sitecore server-side and React client-side power. It seems they are very good match!

Let's dive into code...

I've implemented a simple product list page with React. It's simple but after understanding the implementation logic, then, it can easily be extended. The idea was adding a Sitecore component as usual but giving all responsibility to React components inside Sitecore component. I will show implementation details later in this article.

But before going implementation details, I want to show final result here.




Let's add necessary libraries first.

I've used ReactJS.Net packages, I recommend to have a look at documentation first. It's clear and easy to use. I don't give details how to configure things, they are already explained well in documentation.

Once you finish reading, you can install React.Web.Mvc4 and System.Web.Optimization.React packages via nuget:

Adding Sitecore Component

I've added a page item to list products and added a controller rendering as usual.


Nothing special with adding controller and view. I've created Product controller and ProductList partial view. They looks like this:


   public class ProductController : BaseController
    {
        private readonly IProductRetrieveService _productRetrieveService;

        public ProductController(IProductRetrieveService productRetrieveService)
        {
            _productRetrieveService = productRetrieveService;
        }

        public PartialViewResult ProductList()
        {
            var model = _productRetrieveService.GetProducts((base.DataSourceItem?.ID?.Guid).Value);

            return PartialView(model);
        }

Working with React Components

Special part is in ProductList component. Here, we give all responsibility to React. We only need to do is providing initial data to React component.

@model Training3.Data.ViewModels.Web.Product.ProductListViewModel 

@Html.React("ProductListWrapper", new
{
    initialData = Model
})


Four React components were added:


ProductListWrapper includes other components. I've set state while initializing ProductListWrapper class. Then, necessary data were passed to sub components as seen image below: 



ProductList is straight forward and only responsible to display products. There is no user interaction on it.


class ProductList extends React.Component {
    render() {

        const products = this.props.data.map(product => (
            <div className="col-md-4" key={product.Id}>
                <img src={product.Image.Src} width="200" height="250" />
                <p>{product.Name}</p>
            </div>
        ));

        return (
            <div className="row">
                <div className="col-md-12">
                    <h5>Product List <span className="pull-right">{this.props.pageInfo.TotalRecordCount} products found</span></h5> 
                </div>
                {products}
            </div>
        );
    }
}


ProductCategoryList has checkbox selection events and they are handled as below. The important thing here is after each selection, we pass selected categories with a function to parent component which is ProductListWrapper. See the line marked as red below.


class ProductCategoryList extends React.Component {

    componentWillMount() {
        this.selectedCheckboxes = new Set();
    }

    toggleCheckboxChange = (catId) => {
        console.log("Cat Id: " + catId);

        if (this.selectedCheckboxes.has(catId)) {
            this.selectedCheckboxes.delete(catId);
        } else {
            this.selectedCheckboxes.add(catId);
        }

        this.props.onCategoryChanged(Array.from(this.selectedCheckboxes));
    }

    render() {
        const categories = this.props.data.map(cat => (
            <li className="list-group-item" key={cat.Id}><input type="checkbox" onChange={() => this.toggleCheckboxChange(cat.Id)} /> {cat.Name}</li>
        ));

        return (
            <div>
                <h5>Product Category List</h5>
                <ul className="list-group">
                    {categories}
                </ul>
            </div>
            
        );
    }
}

When new category selection array pass to "onCategoryChanged" function, it is handled in ProductListWrapper like this:



Same logic is used for pagination. Selected categories are already stored in state and we just need new page index when click the page buttons:

handlePageChange(pageIndex) {

   this.loadProducts(this.state.selectedCategories, pageIndex);
}
That's it! It is flexible and you can configure components and actions how you want. 
I haven't worked with React before, this example was the first time for me. I can say that I really liked React and also impressed the power to combine it with Sitecore.

Comments

Popular posts from this blog

Sitecore 9 - Custom Page Events & Filtering with XConnect

This is the first article of a series. I am going to start with creating a custom page event and will show how we can fetch event data using xconnect api. Let's start with reminding demo scenario: Imagine that you have a website displaying movies. Visitors are able to see movie details and take some actions like save movie or share it.  You want to follow the visitors' activities and you want to take some marketing actions based on those activities. For example, if a contact visits a movie more than X time or she/he saves a movie, you want to send those movies to an external system. In addition, there is going to be a limit to send same movie. Such as, it will not be possible to send same movie more than 2 times.  You want to configure this as a marketing automation plan to give flexibility to your marketing managers. They should be able to add configurable rules and activities.  My first focus is movie detail page. I want to track visitors when they visi...

Sitecore Commerce – XC9 Tips – Missing Commerce Components in SXA Toolbox on Experience Editor

I've recently had an issue that commerce components were missing in SXA Toolbox. I setup Sitecore Commerce on top of an existing instance and I already had a SXA website working on it. The idea was to add commerce components and functionality to my existing website. But after commerce setup, the toolbox was still showing default SXA components and commerce components were missing although I add commerce tenant and website modules: I checked Available Renderings under Presentation folder, there was no problem, commerce renderings were there. I created another tenant and website to see if it shows the commerce components in toolbox. Nothing seemed different but I was seeing commerce components for new website and it was missing on existing one. Then, I noticed two things: 1- Selected catalog was empty in content editor (/sitecore/Commerce/Catalog Management/Catalogs) even if I see Habitat_Master catalog in Merchandising section on commerce management panel. 2- Bootstrap ...

Repository & Service Pattern Experiment in Sitecore

I know it is assertive topic for first post, but maybe it is better to be assertive from the beginning! My plan is to keep here with as possible as challenging topics, discussions and experiments. Let's begin. Why Repository & Services Pattern instead of Modular Architecture? First, personal reason: I have experience with Repository & Service Pattern and not with Modular Architecture! I've recently worked for a long term custom big project (not Sitecore project), used this approach and saw its capabilities. During the development, we have faced too many requirement changes, new features etc. We could manage quite well with this approach. I couldn't see Modular Architecture capabilities for a such project yet. Second, technical perspective: Although, I haven't seen Modular Architecture capabilities on a real big project, when I have a look to Habitat and other implementations, I see some difficulties: Difficult to decide modules Big requests or requi...