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 visit the

Sitecore 9 - Creating Custom Segmentation Rule

Predicates are important to create rules for marketing automation and segmented lists. Before going through the details, I am going to remind what I am implementing again. 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.  According to my scenario, I need a rule to filter contacts who visits a movie more than X time. Maybe, we can add one more condition there like in Y days. To creating rule will give flexibility to marketing managers that then they can easily add or remove multiple rules and proceed the