I've been having a lot of fun with JavaScript recently. Building in ECMAScript 6 facilitated by Babel and orchestrated by webpack made web dev workflow super lightweight and seamless. In terms of the rendering technology, I embraced react for all the skunkworks projects. Besides having fun, this boosted the productivity and allowed tapping into the unparalleled set of open source innovations and unlocked new possibilities.
One of them was something I've been contemplating on for a while and brainstorming with Adam Weber and Jakob Christensen was ability to use react for rendering in Sitecore XP.
Sitecore and React. How hard can it be?

Why

Imagine being able to engage a JavaScript developer on a Sitecore project, who just knows how to create components in react and not familiar with neither ASP.NET MVC nor WebForms. How cool would it be? The potential for that sort of setup is mind boggling to me.

How

React is not new to the .NET world, and ReactJS.NET already solves that problem beautifully.
Sitecore and React. How hard can it be?

This library lets you do something truly amazing:

  1. Using ASP.NET Minification and Combination, you get JSX to JavaScript compilation on the web server. That's very creative!

  2. Server-side rendering allows pre-rendering of the initial state of your React components on the server. This not only makes the rendering faster, but should also provide a better SEO story, since the initial state will contain the content for your component.

Now that becomes a possibility, all we need is to find a way to plug that into Sitecore. Since I am an old Sitecorian that still gets nightmares featuring XSLT and WebForms, the first thing I could think of was the good ol' Sitecore.Web.UI.WebControl.

  1. Create a new type of WebControl called ReactControl:
    public class ReactControl : Sitecore.Web.UI.WebControl

  2. Then simply override the DoRender method:
    protected override void DoRender(HtmlTextWriter output)

  3. This is where you can render html coming from virtually any view engine, including ReactJS.NET:
    output.Write(reactComponent.RenderHtml());

  4. In order to get the reactComponent, you need to access an instance of IReactEnvironment, pass it the name of the desired component and the optional props:
    IReactComponent reactComponent = Environment.CreateComponent(name, props);

    The name is needed to find the react component in the 'registry'.

    As for the props, think about them as the incoming parameters needed for the react control for behavior and look and feel.

  5. The value for name should come to ReactControl from outside. By simply declaring the Name property we can make that happen:
    public string Name { get; set; }

  6. As for props, can we pass content fields from the Sitecore context item or DataSource item? Yes, we can:

  7. To enable react take over on the front-end, we need to render JavaScript from DoRender:
    var js = reactComponent.RenderJavaScript(); output.Write(string.Format("<script>{0}</script>", js);

  8. To compile JSX to JavaScript, you would need to register a BabelBundle using ASP.NET Bundling and Minification:
    BundleTable.Bundles.Add(new BabelBundle("~/bundle/react").IncludeDirectory("~/jsx", "*.jsx"));

    Please refer to the official ReactJS.NET docs on this topic here.

  9. Register react components within ReactJS.NET environment:
    ReactSiteConfiguration.Configuration .SetReuseJavaScriptEngines(true) .AddScript("~/jsx/HelloWorld.jsx");

    You probably don't want to modify this code every time a new component needs to be registered, so this approach of calling AddScript will have to be turned to a more dynamic approach.

    More about this aspect in official ReactJS.NET docs here.

    From Sitecore integration perspective, you can do both #8 and #9 steps either from the <initialize /> pipeline, or as a custom IHook implementation.

  10. To complete the integration, add the following to the <head> of your layout:

    • render the bundle we registered above: <%: Scripts.Render("~/bundle/react") %>
    • reference to react library:

    <script src="https://fb.me/react-0.14.0.min.js"></script> <script src="https://fb.me/react-dom-0.14.0.min.js"></script>

  11. Final step to upgrade this to the first-class Sitecore rendering and register ReactControl as a WebControl, simply create an item from the WebControl template under /sitecore/layouts/renderings and fill out Namespace, Tag, Tag Prefix, Assembly and Parameters fields:

    alt

    Notice the value of the Parameters field? The 'HelloWorld' value will be passed to ReactControl's Name property (step #5 above).

  12. Having the rendering defined as item allows for binding the ReactControl to placeholder the usual Sitecore way. So let's bind our HelloWorld rendering to the Home page:
    alt

  13. Now in order to render something, we need the actual react rendering we referenced above. Simply create a .jsx file under /jsx folder with our first react component (see step #9 where we referenced ~/jsx/HelloWorld.jsx):

    var HelloWorld = React.createClass({ render: function() { return ( <div> <h1> Rendering <span>{this.props.title}</span> from React! </h1> </div> ); } });

    Notice that this component isn't doing much. It's sort of dumb. Simply taking the 'title' from props and rendering it along with other text in <h1 />.

Result

Here is the output of the home page. The value of the title is coming from the DataSource item. So we are getting 'Home' as the result:

alt

Adding a stateful Counter rendering

The walkthrough above featured a dumb HelloWorld component, which demonstrates the integration aspects, but it is a pretty boring example. Let's spice it up.

Implementing a basic Counter is quite popular react sample. In order to implement it with Sitecore-React integration, we would need:

  1. Standard Counter.jsx component from react samples.

    This component is stateful. Within the H1 it renders some static text, the value from the title props, which comes from the context item and the value of the counter.

  2. Create Counter rendering item under /layout/renderings the same way we did it with HelloWorld above.

  3. Bind Counter rendering to the placeholder as you do with any rendering.

That's it! Pretty short workflow.

React.js counter rendered in Sitecore

Wait...What?

You got it. Sitecore still owns the rendering end to end, but the rendering is done in react/JavaScript.
Essetially, this is the first step to making react a first class citizen within Sitecore's rendering stack. Among current options out there (MVC, WebForms, Server/Web controls, XSLT), this one has one key benefit besides the obvious one (using react) - you can have a initial rendering happen on the server, and then take over on the client, allowing doing proper JavaScript development on a Sitecore solution without sacrificing all the benefits of the Sitecore rendering engine. No need to wrap Sitecore in API and build your app stand-alone. None of that complexity.

Among other things

While this is a crazy experiment, and the approach is yet to be proven in field, I am super excited about the potential opportunity here. This approach vs. the traditional way of building single page/dynamic/realtime web applications outside of Sitecore rendering engine, where Sitecore is used as a wrapped content service API, has a ton of benefits:

  • React components have no Sitecore specifics or dependencies and can be implemented by JavaScript developers in 'parallel thread' to tranditional Sitecore development, establishing a nice contract between BE and FE developers.

  • Experience Editor works:

Sitecore react integration in Experience Editor

To enable editing, it's required to set inner html differently: <h1 dangerouslySetInnerHTML={{__html: this.props.title}}></h1>

  • Marketers have full control over the layout positioning and can alter the presentation without dev involvement.

  • Sitecore Tracker works by default => analytics will be captured.

  • Support for Datasources => personalization, MV testing, and all related goodies.

Show me the code

Here is the link to the public github repo with the sitecore-react integration code and some samples. It includes the react control items bound to the Home page with standard TitleText and HeaderImage components, as well as the Counter component.

Pathfinder

If you are planning on building an app with this, I'd suggest turning to Sitecore.Pathfinder. Jakob just added support for react renderings 2 days ago. While this was inspired by the sitecore-react integration, instead of using Sitecore WebControl as integration point, Jakob did something much better and cleaner - plugged into the Sitecore MVC rendering pipeline.
Besides this new feature, Pathfinder got an impressive set of innovations, which will take the Sitecore development workflow to the next level.

Next steps

  • If you are not familiar with react, I suggest looking into the basic getting started guides. Fortunately, there is a ton of documentation and courses out there.

  • Give Sitecore.Pathfinder a go. There is a ton of potential there, and you can definitely increase the developer productivity. When you do the first build there, it simply feels like magic :)

Need feedback

Please let me know what do you think about using this for your use cases and Sitecore customers. Please share your thoughts in comments below or on twitter.