Automatically Parsing Inline React JSX in MVC View

 

        Introduction:

 

                 Facebook React.js becoming popular day by day. Some guys are even preferring to use React inseatd of Web Components. React support JSX syntax which is a concise and familiar syntax for defining tree structures with attributes. A good thing about React JSX is that it can be automatically parse by using Reactjs.net library in our ASP.NET MVC application. When we install React.Web.Mvc4 package in our ASP.NET MVC(4 or 5) application, it will register JsxHandlerFactory http handler for requests with jsx extension. So, request with jsx extension will be parsed automatically to compiled javascript without writing a single line of code at server. But what if we want to write JSX inline in your MVC views.  In this article, I will show you how we can parse inline JSX at server.

 

        Description:

 

                    Assuming that we have ASP.NET MVC application, installed React.Web.Mvc4 package  and one of our view have inline JSX. Let say we have this sample (available on Facebook github page),

 

    <script type="text/jsx">
        var TodoList = React.createClass({
          render: function() {
            var createItem = function(itemText) {
              return <li>{itemText}</li>;
            };
            return <ul>{this.props.items.map(createItem)}</ul>;
          }
        });
        var TodoApp = React.createClass({
          getInitialState: function() {
            return {items: [], text: ''};
          },
          onChange: function(e) {
            this.setState({text: e.target.value});
          },
          handleSubmit: function(e) {
            e.preventDefault();
            var nextItems = this.state.items.concat([this.state.text]);
            var nextText = '';
            this.setState({items: nextItems, text: nextText});
          },
          render: function() {
            return (
              <div>
                <h3>TODO</h3>
                <TodoList items={this.state.items} />
                <form onSubmit={this.handleSubmit}>
                  <input onChange={this.onChange} value={this.state.text} />
                  <button>{'Add #' + (this.state.items.length + 1)}</button>
                </form>
              </div>
            );
          }
        });

        React.render(<TodoApp />, document.body);
    </script>

 

                    There may be lot of ways to parse JSX but here we will use a custom WebViewPage. Add ReactAwareWebViewPage class in your app,

 

    public class ReactAwareWebViewPage<T> : WebViewPage<T>
    {
        public override void ExecutePageHierarchy()
        {
            var writer = new StringWriter();
            OutputStack.Push(writer);
            base.ExecutePageHierarchy();
            OutputStack.Pop();
            Response.Clear();
            var output = writer.ToString();
            var regex = new Regex("<script type=['\"]text/jsx['\"]>(?<jsx>([^<]|<[^/]|</[^s]|</s[^c]|</sc[^r])*)</script>", 
                RegexOptions.IgnoreCase | RegexOptions.Multiline);
            var transformer = React.AssemblyRegistration.Container.Resolve<React.JsxTransformer>();
            output = regex.Replace(output,
                m => 
                    string.Format("<script>{0}</script>", 
                    transformer.TransformJsx(m.Groups["jsx"].Value)));
            Response.Write(output);
        }

        public override void Execute()
        {
        }
    }

 

                    The only interesting thing above class is JsxTransformer class. First, I am grabbing the JSX contents from html and then passing the JSX to JsxTransformer.TransformJsx method which will return us the compiled javascript. Finally, I am just formatting and re-writing the output to response. Just remember to register this WebViewPage.

 

 

 
    <pages pageBaseType="ReactTest.Controllers.ReactAwareWebViewPage">

 

 

 

                   

        Summary:

                    In this article, I showed you how to automatically parse inline JSX into compiled javascript within your MVC view. The JsxTransformer.TransformJsx method do all the parsing.

No Comments