Skip to content

Resolves Issue #521 Draft #541

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Jun 10, 2018
3 changes: 2 additions & 1 deletion src/React.Core/ReactComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ public object Props
_configuration.JsonSerializerSettings);
}
}
public bool ClientOnly { get; set; }

/// <summary>
/// Initializes a new instance of the <see cref="ReactComponent"/> class.
Expand Down Expand Up @@ -233,7 +234,7 @@ public virtual string RenderJavaScript()
/// <returns>JavaScript</returns>
public virtual void RenderJavaScript(TextWriter writer)
{
writer.Write("ReactDOM.hydrate(");
writer.Write(ClientOnly ? "ReactDOM.render(" : "ReactDOM.hydrate(");
WriteComponentInitialiser(writer);
writer.Write(", document.getElementById(\"");
writer.Write(ContainerId);
Expand Down
21 changes: 11 additions & 10 deletions src/React.Core/ReactEnvironment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/

Expand All @@ -22,7 +22,7 @@
namespace React
{
/// <summary>
/// Request-specific ReactJS.NET environment. This is unique to the individual request and is
/// Request-specific ReactJS.NET environment. This is unique to the individual request and is
/// not shared.
/// </summary>
public class ReactEnvironment : IReactEnvironment, IDisposable
Expand Down Expand Up @@ -70,7 +70,7 @@ public class ReactEnvironment : IReactEnvironment, IDisposable
/// </summary>
protected readonly Lazy<string> _version = new Lazy<string>(GetVersion);
/// <summary>
/// Contains an engine acquired from a pool of engines. Only used if
/// Contains an engine acquired from a pool of engines. Only used if
/// <see cref="IReactSiteConfiguration.ReuseJavaScriptEngines"/> is enabled.
/// </summary>
protected Lazy<PooledJsEngine> _engineFromPool;
Expand Down Expand Up @@ -141,7 +141,7 @@ IReactIdGenerator reactIdGenerator
_fileSystem = fileSystem;
_fileCacheHash = fileCacheHash;
_reactIdGenerator = reactIdGenerator;
_babelTransformer = new Lazy<IBabel>(() =>
_babelTransformer = new Lazy<IBabel>(() =>
new Babel(this, _cache, _fileSystem, _fileCacheHash, _config)
);
_engineFromPool = new Lazy<PooledJsEngine>(() => _engineFactory.GetEngine());
Expand Down Expand Up @@ -304,6 +304,7 @@ public virtual IReactComponent CreateComponent<T>(string componentName, T props,

var component = new ReactComponent(this, _config, _reactIdGenerator, componentName, containerId)
{
ClientOnly = clientOnly,
Props = props,
ServerOnly = serverOnly
};
Expand All @@ -329,7 +330,7 @@ public virtual IReactComponent CreateComponent(IReactComponent component, bool c
}

/// <summary>
/// Renders the JavaScript required to initialise all components client-side. This will
/// Renders the JavaScript required to initialise all components client-side. This will
/// attach event handlers to the server-rendered HTML.
/// </summary>
/// <param name="clientOnly">True if server-side rendering will be bypassed. Defaults to false.</param>
Expand All @@ -344,7 +345,7 @@ public virtual string GetInitJavaScript(bool clientOnly = false)
}

/// <summary>
/// Renders the JavaScript required to initialise all components client-side. This will
/// Renders the JavaScript required to initialise all components client-side. This will
/// attach event handlers to the server-rendered HTML.
/// </summary>
/// <param name="writer">The <see cref="T:System.IO.TextWriter" /> to which the content is written</param>
Expand All @@ -371,12 +372,12 @@ public virtual void GetInitJavaScript(TextWriter writer, bool clientOnly = false

/// <summary>
/// Attempts to execute the provided JavaScript code using a non-pooled JavaScript engine (ie.
/// creates a new JS engine per-thread). This is because Babel uses a LOT of memory, so we
/// creates a new JS engine per-thread). This is because Babel uses a LOT of memory, so we
/// should completely dispose any engines that have loaded Babel in order to conserve memory.
///
///
/// If an exception is thrown, retries the execution using a new thread (and hence a new engine)
/// with a larger maximum stack size.
/// This is required because JSXTransformer uses a huge stack which ends up being larger
/// This is required because JSXTransformer uses a huge stack which ends up being larger
/// than what ASP.NET allows by default (256 KB).
/// </summary>
/// <typeparam name="T">Type to return from JavaScript call</typeparam>
Expand All @@ -396,7 +397,7 @@ public virtual T ExecuteWithBabel<T>(string function, params object[] args)

catch (Exception)
{
// Assume the exception MAY be an "out of stack space" error. Try running the code
// Assume the exception MAY be an "out of stack space" error. Try running the code
// in a different thread with larger stack. If the same exception occurs, we know
// it wasn't a stack space issue.
T result = default(T);
Expand Down
4 changes: 2 additions & 2 deletions src/React.Sample.Cassette/Views/Home/Index.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
@Html.React("CommentsBox", new { initialComments = Model.Comments })

<!-- Load all required scripts (React + the site's scripts) -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.0.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.0.0/umd/react-dom.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.4.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.4.0/umd/react-dom.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prop-types/15.6.0/prop-types.js"></script>
@Bundles.RenderScripts()
<!-- Render the code to initialise the component -->
Expand Down
4 changes: 2 additions & 2 deletions src/React.Sample.CoreMvc/Views/Home/Index.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
@Html.React("CommentsBox", new { initialComments = Model.Comments, ThrowRenderError = Model.ThrowRenderError })

<!-- Load all required scripts (React + the site's scripts) -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.0.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.0.0/umd/react-dom.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.4.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.4.0/umd/react-dom.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prop-types/15.6.0/prop-types.js"></script>
<script src="~/js/Sample.jsx"></script>
<!-- Render the code to initialise the component -->
Expand Down
4 changes: 2 additions & 2 deletions src/React.Sample.Mvc4/Views/Home/Index.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
@Html.React("CommentsBox", new { initialComments = Model.Comments, page = Model.Page })

<!-- Load all required scripts (React + the site's scripts) -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.0.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.0.0/umd/react-dom.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.4.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.4.0/umd/react-dom.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prop-types/15.6.0/prop-types.js"></script>
@Scripts.Render("~/bundles/main")
<!-- Render the code to initialise the component -->
Expand Down
4 changes: 2 additions & 2 deletions src/React.Sample.Owin/Content/Index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
</head>
<body>
<div id="container"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.0.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.0.0/umd/react-dom.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.4.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.4.0/umd/react-dom.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prop-types/15.6.0/prop-types.js"></script>
<script type="text/javascript" src="Sample.jsx"></script>
<script type="text/javascript">
Expand Down
4 changes: 2 additions & 2 deletions src/React.Sample.Webpack/Views/Home/Index.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
@Html.React("Components.CommentsBox", new { initialComments = Model.Comments })

<!-- Load all required scripts (React + the site's scripts) -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.0.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.0.0/umd/react-dom.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.4.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.4.0/umd/react-dom.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prop-types/15.6.0/prop-types.js"></script>
<script src="@Url.Content("~/build/client.bundle.js")"></script>
<!-- Render the code to initialise the component -->
Expand Down
42 changes: 41 additions & 1 deletion tests/React.Tests/Core/ReactComponentTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,46 @@ public void RenderJavaScriptShouldCallRenderComponent()
);
}

[Fact]
public void RenderJavaScriptShouldCallRenderComponentWithReactDOMRender()
{
var environment = new Mock<IReactEnvironment>();
var config = new Mock<IReactSiteConfiguration>();
var reactIdGenerator = new Mock<IReactIdGenerator>();

var component = new ReactComponent(environment.Object, config.Object, reactIdGenerator.Object, "Foo", "container")
{
ClientOnly = true,
Props = new { hello = "World" }
};
var result = component.RenderJavaScript();

Assert.Equal(
@"ReactDOM.render(React.createElement(Foo, {""hello"":""World""}), document.getElementById(""container""))",
result
);
}

[Fact]
public void RenderJavaScriptShouldCallRenderComponentwithReactDOMHydrate()
{
var environment = new Mock<IReactEnvironment>();
var config = new Mock<IReactSiteConfiguration>();
var reactIdGenerator = new Mock<IReactIdGenerator>();

var component = new ReactComponent(environment.Object, config.Object, reactIdGenerator.Object, "Foo", "container")
{
ClientOnly = false,
Props = new { hello = "World" }
};
var result = component.RenderJavaScript();

Assert.Equal(
@"ReactDOM.hydrate(React.createElement(Foo, {""hello"":""World""}), document.getElementById(""container""))",
result
);
}

[Theory]
[InlineData("Foo", true)]
[InlineData("Foo.Bar", true)]
Expand Down Expand Up @@ -284,7 +324,7 @@ public void ExceptionThrownIsHandled()
Action<Exception, string, string> customHandler = (ex, name, id) => customHandlerInvoked = true;
component.RenderHtml(exceptionHandler: customHandler);
Assert.True(customHandlerInvoked);

// Custom exception handler set
Exception caughtException = null;
config.Setup(x => x.ExceptionHandler).Returns((ex, name, id) => caughtException = ex);
Expand Down
4 changes: 2 additions & 2 deletions tutorial-code/Views/Home/Index.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
submitUrl = Url.Action("AddComment"),
pollInterval = 2000,
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.0.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.0.0/umd/react-dom.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.4.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.4.0/umd/react-dom.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prop-types/15.6.0/prop-types.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/remarkable/1.7.1/remarkable.min.js"></script>
<script src="@Url.Content("~/js/tutorial.jsx")"></script>
Expand Down