Razor to React to TypeScript

Previously in part 2 I  RE-WROTE some simple Razor as a React JSX script. And here is the same JSX script in Typescript.

 class RequisitionBox extends React.Component<IRequisitionProps,any> {
   constructor(props: any) {
   super();
    this.state = { requistionData: props.requistionData };
 }
 render() {
  var requisitionNodes = this.state.requistionData.map(requisition    => <RequisitionItem Id={requisition.Id} DateCreated={requisition.DateCreated} />);
  return (
       <div>
        <h4>Requisitions</h4>
        <div>{requisitionNodes}</div>
      </div>
       );
     }
 }
 class RequisitionItem extends React.Component<IRequistionItem, any> {
   render() {
        return (
          <div> 
           <div> Requistion: {this.props.Id}</div>
           <div> Name: {this.props.DateCreated}</div>
         </div>
    );
  }
 }
 Yes its almost identical ! The main differences are that we no longer use Reacts  getInitialState but rather set the initial state in the constructor which I think is … well it doesn’t matter that’s just how you do it in typescript. Also it uses generics.
I also created two interfaces (which have no meaning in javascript and are therefore not trans-piled  into the outputted js).
interface IRequisitionProps {
 requistionData: string
}
interface IRequistionItem {
 Id: number;
 DateCreated: any;
}

This is obviously extra code that you would not have to write in plain JSX. But the advantages of using typescript are now you have type safety, intellisense and debugging as the code renders.

Using http://json2ts.com/ you can automatically create your interface to help mimic your server side model on the client. So by supplying the json model  emitted by server side controller


{"Id":2011055,"DateCreated":null}

We got an auto generated IRequisitionItem interface – not a big deal in such a trivial example but will be a time save on more complex models.

As a typescript novice the biggest issue I found in converting from JSX to TSX  was to overthink the conversion process. Its important to to remember the actual code is almost exactly the same, but with seat belts on, after all it transpiles to the same javascript.


var __extends = (this && this.__extends) || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var RequisitionBox = (function (_super) {
    __extends(RequisitionBox, _super);
    function RequisitionBox(props) {
        _super.call(this);
        this.state = { requistionData: props.requistionData };
    }
    RequisitionBox.prototype.render = function () {
        var requisitionNodes = this.state.requistionData.map(function (requisition) {
            return React.createElement(RequisitionItem, {"Id": requisition.Id, "DateCreated": requisition.DateCreated});
        });
        return (React.createElement("div", {"className": "requisition"}, React.createElement("h1", null, "Comments"), React.createElement("div", {"className": "requisitionList"}, requisitionNodes)));
    };
    return RequisitionBox;
})(React.Component);
var RequisitionItem = (function (_super) {
    __extends(RequisitionItem, _super);
    function RequisitionItem() {
        _super.apply(this, arguments);
    }
    RequisitionItem.prototype.render = function () {
        return (React.createElement("div", null, React.createElement("div", {"className": "col-md-6 "}, " Requistion: ", this.props.Id), React.createElement("div", {"className": "col-md-6 "}, " Name: ", this.props.DateCreated)));
    };
    return RequisitionItem;
})(React.Component);

 

Razor To React

Part 2

Part 1 is here

To recap the aim is to see if I can remove existing Razor syntax from mvc.net views and replace it with a javascript view framework without having to rewrite the server side .net code

The challenge is to see how easily and succinctly can the following syntax be replaced

foreach (var order in @Model.PurchaseOrders)
{
 <div class="col-md-6">Requisition: @order.Id</div>
 <div class="col-md-6 ">Date created: @order.DateCreated.ToShortDateString()</div>
}

In part 1 I was able to replace Razor fairly easily but due to my misconceptions the code was unnecessarily verbose.

After some sage advice I came up with the following React jsx


var RequisitionBox = React.createClass({
 getInitialState: function() {
 return { requistionData: this.props.initialData };
 },
 render() {
 var requisitionNodes = this.state.requistionData.map(requisition =>
 <Requistion Id={requisition.Id} DateCreated= 
                 { requisition.DateCreated}></Requistion>
 );

 return (
 <div className="requisition">
 <h1>Requistions List</h1>
 <div className="requisitionList">{requisitionNodes}
 </div>
 </div>
 );
 }
});

var Requistion = React.createClass({
 render() {
 return (
 <div> 
 <div className="col-md-6 "> Requistion:{this.props.Id}</div>
 <div className="col-md-6 ">{this.props.DateCreated}</div>
 </div>

 );
 }
});

The main difference now is that the React script is no longer handling the fetching of the data from the server. Instead we are now using server side rendering to pre-render the initial state of React components. The bonus of doing this is that it speeds up initial page load. To do this its as simple as

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

Now we're cooking with gas. No new controller actions had to be created . No Ajax or DOM manupilation was involved. Simply render the specified React component and give it your model data. Even though the React script could be compressed into a single class to make it more succinct - however I think its better to break it into small components even if its more verbose.

Part 3 Journey into TypeScript.

Journey into JavaScript Frameworks – React

Having come out of our tech meeting with instructions to choose a MV* javascript framework for future UI development I was initially overcome with a phenomena known as a Paradox of Choice .

Eventually the ailment passed and finally as an exercise I decided to see how easy it would be to pull out the razor engine rendering from an existing mvc.net web app UI and to replace it with ReactJS, without having to change the backend controller or logic.

It was fairly easy to integrate reactjs into the existing mvc.net application and within a short time I was able to replace the razor code with JSX (react javascript) using this this tutorial .

The task was to replace replace this simple  razor syntax with react JSX.

foreach (var order in @Model.PurchaseOrders)
{
<div class="col-md-6">Requisition: @order.Id</div>
<div class="col-md-6 ">Date created: @order.DateCreated.ToShortDateString()</div>
}

And here is what I came up with initially.


var RequisitionBox = React.createClass({
loadCommentsFromServer: function () {
var xhr = new XMLHttpRequest();
xhr.open('get', this.props.url, true);
xhr.onload = function () {
var data = JSON.parse(xhr.responseText);
this.setState({ data: data });
}.bind(this);
xhr.send();
},
getInitialState: function () {
return { data: [] };
},
componentDidMount: function () {
this.loadCommentsFromServer();
},
render: function() {

 return (
 <div className="requisition">
 <h1>Requistions List</h1>
 <div className="requisitionList">{requisitionNodes}
 </div>
 </div>
 );
 }
});

var Requistion = React.createClass({
 render() {
 return (
 <div> 
 <div className="col-md-6 "> Requistion:{this.props.Id}</div>
 <div className="col-md-6 ">{this.props.DateCreated}</div>
 </div>

 );
 }
});ReactDOM.render( document.getElementById('content') );

And that’s it !

Seems like a lot more code than the original 4 lines. Clearly I have done something wrong.

In part 2 I will look at how to refactor this code so that the React component is no longer responsible for fetching the data and also  how we can render the component server side to improve preformance. Or to give it it’s fancy name – Isomorphic Javascript .