Skip to content

Instantly share code, notes, and snippets.

@prabirshrestha
Last active September 15, 2016 09:29
Show Gist options
  • Save prabirshrestha/10044666 to your computer and use it in GitHub Desktop.
Save prabirshrestha/10044666 to your computer and use it in GitHub Desktop.
Nancy ReactJS View Engine
/** @jsx React.DOM */
// views/hello.jsx
var HelloWorld = React.createClass({
render: function () {
return (
<div>Hello {this.props.firstName} {this.props.lastName}.</div>
);
}
});
module.exports = HelloWorld;
using Nancy;
namespace NancyReactServerSide
{
public class HelloWorldModule : NancyModule
{
public HelloWorldModule()
{
// note: models are passed as reactjs props. ViewBag is ignored
Get["/"] = _ => View["hello", new { firstName = "Prabir", lastName = "Shrestha" }];
Get["/hi"] = _ => View["hi", new { name = Request.Query.name.Value }];
}
}
}
/** @jsx React.DOM */
// views/hi.jsx
var Hi = React.createClass({
render: function () {
return (
<div>Hi {this.props.name}</div>
);
}
});
module.exports = Hi;
using System;
using System.Collections.Generic;
using System.IO;
using Nancy;
using Nancy.Responses;
using Nancy.ViewEngines;
using React;
namespace NancyReactServerSide
{
public class ReactJsViewEngine : IViewEngine
{
private readonly IEnumerable<string> _extensions = new[] { "jsx", "js" };
public IEnumerable<string> Extensions
{
get { return _extensions; }
}
public void Initialize(ViewEngineStartupContext viewEngineStartupContext)
{
}
public Response RenderView(ViewLocationResult viewLocationResult, dynamic model, IRenderContext renderContext)
{
return new HtmlResponse(statusCode: HttpStatusCode.OK, contents: stream => {
var html = RenderComponent(viewLocationResult, model, renderContext);
var writer = new StreamWriter(stream);
writer.Write(html);
writer.Flush();
});
}
public string RenderComponent(ViewLocationResult viewLocationResult, dynamic model, IRenderContext renderContext)
{
string content;
using (var reader = viewLocationResult.Contents.Invoke())
{
content = reader.ReadToEnd();
}
var react = new ReactEnvironment(
new JavaScriptEngineFactory(),
new ReactSiteConfiguration(),
new NullReactCache(),
new NullReactFileSystem());
react.Execute("module = { exports: {} };");
// this is bad and should be cached instead
var js = react.TransformJsx(content);
react.Execute(js);
// ugly hack for now as ReactJS.NET CreateComponent requires variable name and doesn't support common js modules :(
react.Execute(";var __ReactComponent__ = module.exports;");
IReactComponent component = react.CreateComponent<object>("__ReactComponent__", model);
var html = component.RenderHtml();
return html;
}
// we don't use this currently
class NullReactCache : ICache
{
public T GetOrInsert<T>(string key, TimeSpan slidingExpiration, Func<T> getData, IEnumerable<string> cacheDependencyFiles = null,
IEnumerable<string> cacheDependencyKeys = null)
{
return getData();
}
}
// we don't use this currently
class NullReactFileSystem : IFileSystem
{
public string MapPath(string relativePath)
{
throw new NotImplementedException();
}
public string ReadAsString(string relativePath)
{
throw new NotImplementedException();
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment