Skip to content

Commit 12ff098

Browse files
suhailnawdustinsoftware
authored andcommitted
Resolves Issue #521 Draft (#541)
* Added ClientOnly property to ReactComponent * added conditional to RenderJavascript to decide between ReactDOM.render vs ReactDOM.hydrate * Added 2 tests to check if correct method ReactDOM.render or ReactDOM.hydrate used when toggling clientOnly parameter in ReactComponent * Made available ClientOnly and correctly implemented ternary operator using Write * Removed redundant call to ClientOnly * Changed tests to correctly take in ClientOnly * Changed incorrect punctuation in test file * Corrected tests to use render if true * Update examples to react 16.4
1 parent c7c0058 commit 12ff098

File tree

9 files changed

+66
-24
lines changed

9 files changed

+66
-24
lines changed

Diff for: src/React.Core/ReactComponent.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ public object Props
9595
_configuration.JsonSerializerSettings);
9696
}
9797
}
98+
public bool ClientOnly { get; set; }
9899

99100
/// <summary>
100101
/// Initializes a new instance of the <see cref="ReactComponent"/> class.
@@ -233,7 +234,7 @@ public virtual string RenderJavaScript()
233234
/// <returns>JavaScript</returns>
234235
public virtual void RenderJavaScript(TextWriter writer)
235236
{
236-
writer.Write("ReactDOM.hydrate(");
237+
writer.Write(ClientOnly ? "ReactDOM.render(" : "ReactDOM.hydrate(");
237238
WriteComponentInitialiser(writer);
238239
writer.Write(", document.getElementById(\"");
239240
writer.Write(ContainerId);

Diff for: src/React.Core/ReactEnvironment.cs

+11-10
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* All rights reserved.
44
*
55
* This source code is licensed under the BSD-style license found in the
6-
* LICENSE file in the root directory of this source tree. An additional grant
6+
* LICENSE file in the root directory of this source tree. An additional grant
77
* of patent rights can be found in the PATENTS file in the same directory.
88
*/
99

@@ -22,7 +22,7 @@
2222
namespace React
2323
{
2424
/// <summary>
25-
/// Request-specific ReactJS.NET environment. This is unique to the individual request and is
25+
/// Request-specific ReactJS.NET environment. This is unique to the individual request and is
2626
/// not shared.
2727
/// </summary>
2828
public class ReactEnvironment : IReactEnvironment, IDisposable
@@ -70,7 +70,7 @@ public class ReactEnvironment : IReactEnvironment, IDisposable
7070
/// </summary>
7171
protected readonly Lazy<string> _version = new Lazy<string>(GetVersion);
7272
/// <summary>
73-
/// Contains an engine acquired from a pool of engines. Only used if
73+
/// Contains an engine acquired from a pool of engines. Only used if
7474
/// <see cref="IReactSiteConfiguration.ReuseJavaScriptEngines"/> is enabled.
7575
/// </summary>
7676
protected Lazy<PooledJsEngine> _engineFromPool;
@@ -141,7 +141,7 @@ IReactIdGenerator reactIdGenerator
141141
_fileSystem = fileSystem;
142142
_fileCacheHash = fileCacheHash;
143143
_reactIdGenerator = reactIdGenerator;
144-
_babelTransformer = new Lazy<IBabel>(() =>
144+
_babelTransformer = new Lazy<IBabel>(() =>
145145
new Babel(this, _cache, _fileSystem, _fileCacheHash, _config)
146146
);
147147
_engineFromPool = new Lazy<PooledJsEngine>(() => _engineFactory.GetEngine());
@@ -304,6 +304,7 @@ public virtual IReactComponent CreateComponent<T>(string componentName, T props,
304304

305305
var component = new ReactComponent(this, _config, _reactIdGenerator, componentName, containerId)
306306
{
307+
ClientOnly = clientOnly,
307308
Props = props,
308309
ServerOnly = serverOnly
309310
};
@@ -329,7 +330,7 @@ public virtual IReactComponent CreateComponent(IReactComponent component, bool c
329330
}
330331

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

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

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

397398
catch (Exception)
398399
{
399-
// Assume the exception MAY be an "out of stack space" error. Try running the code
400+
// Assume the exception MAY be an "out of stack space" error. Try running the code
400401
// in a different thread with larger stack. If the same exception occurs, we know
401402
// it wasn't a stack space issue.
402403
T result = default(T);

Diff for: src/React.Sample.Cassette/Views/Home/Index.cshtml

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@
2020
@Html.React("CommentsBox", new { initialComments = Model.Comments })
2121

2222
<!-- Load all required scripts (React + the site's scripts) -->
23-
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.0.0/umd/react.development.js"></script>
24-
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.0.0/umd/react-dom.development.js"></script>
23+
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.4.0/umd/react.development.js"></script>
24+
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.4.0/umd/react-dom.development.js"></script>
2525
<script src="https://cdnjs.cloudflare.com/ajax/libs/prop-types/15.6.0/prop-types.js"></script>
2626
@Bundles.RenderScripts()
2727
<!-- Render the code to initialise the component -->

Diff for: src/React.Sample.CoreMvc/Views/Home/Index.cshtml

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
@Html.React("CommentsBox", new { initialComments = Model.Comments, ThrowRenderError = Model.ThrowRenderError })
1818

1919
<!-- Load all required scripts (React + the site's scripts) -->
20-
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.0.0/umd/react.development.js"></script>
21-
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.0.0/umd/react-dom.development.js"></script>
20+
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.4.0/umd/react.development.js"></script>
21+
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.4.0/umd/react-dom.development.js"></script>
2222
<script src="https://cdnjs.cloudflare.com/ajax/libs/prop-types/15.6.0/prop-types.js"></script>
2323
<script src="~/js/Sample.jsx"></script>
2424
<!-- Render the code to initialise the component -->

Diff for: src/React.Sample.Mvc4/Views/Home/Index.cshtml

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
@Html.React("CommentsBox", new { initialComments = Model.Comments, page = Model.Page })
1818

1919
<!-- Load all required scripts (React + the site's scripts) -->
20-
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.0.0/umd/react.development.js"></script>
21-
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.0.0/umd/react-dom.development.js"></script>
20+
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.4.0/umd/react.development.js"></script>
21+
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.4.0/umd/react-dom.development.js"></script>
2222
<script src="https://cdnjs.cloudflare.com/ajax/libs/prop-types/15.6.0/prop-types.js"></script>
2323
@Scripts.Render("~/bundles/main")
2424
<!-- Render the code to initialise the component -->

Diff for: src/React.Sample.Owin/Content/Index.html

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
</head>
99
<body>
1010
<div id="container"></div>
11-
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.0.0/umd/react.development.js"></script>
12-
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.0.0/umd/react-dom.development.js"></script>
11+
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.4.0/umd/react.development.js"></script>
12+
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.4.0/umd/react-dom.development.js"></script>
1313
<script src="https://cdnjs.cloudflare.com/ajax/libs/prop-types/15.6.0/prop-types.js"></script>
1414
<script type="text/javascript" src="Sample.jsx"></script>
1515
<script type="text/javascript">

Diff for: src/React.Sample.Webpack/Views/Home/Index.cshtml

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
@Html.React("Components.CommentsBox", new { initialComments = Model.Comments })
1717

1818
<!-- Load all required scripts (React + the site's scripts) -->
19-
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.0.0/umd/react.development.js"></script>
20-
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.0.0/umd/react-dom.development.js"></script>
19+
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.4.0/umd/react.development.js"></script>
20+
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.4.0/umd/react-dom.development.js"></script>
2121
<script src="https://cdnjs.cloudflare.com/ajax/libs/prop-types/15.6.0/prop-types.js"></script>
2222
<script src="@Url.Content("~/build/client.bundle.js")"></script>
2323
<!-- Render the code to initialise the component -->

Diff for: tests/React.Tests/Core/ReactComponentTest.cs

+41-1
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,46 @@ public void RenderJavaScriptShouldCallRenderComponent()
213213
);
214214
}
215215

216+
[Fact]
217+
public void RenderJavaScriptShouldCallRenderComponentWithReactDOMRender()
218+
{
219+
var environment = new Mock<IReactEnvironment>();
220+
var config = new Mock<IReactSiteConfiguration>();
221+
var reactIdGenerator = new Mock<IReactIdGenerator>();
222+
223+
var component = new ReactComponent(environment.Object, config.Object, reactIdGenerator.Object, "Foo", "container")
224+
{
225+
ClientOnly = true,
226+
Props = new { hello = "World" }
227+
};
228+
var result = component.RenderJavaScript();
229+
230+
Assert.Equal(
231+
@"ReactDOM.render(React.createElement(Foo, {""hello"":""World""}), document.getElementById(""container""))",
232+
result
233+
);
234+
}
235+
236+
[Fact]
237+
public void RenderJavaScriptShouldCallRenderComponentwithReactDOMHydrate()
238+
{
239+
var environment = new Mock<IReactEnvironment>();
240+
var config = new Mock<IReactSiteConfiguration>();
241+
var reactIdGenerator = new Mock<IReactIdGenerator>();
242+
243+
var component = new ReactComponent(environment.Object, config.Object, reactIdGenerator.Object, "Foo", "container")
244+
{
245+
ClientOnly = false,
246+
Props = new { hello = "World" }
247+
};
248+
var result = component.RenderJavaScript();
249+
250+
Assert.Equal(
251+
@"ReactDOM.hydrate(React.createElement(Foo, {""hello"":""World""}), document.getElementById(""container""))",
252+
result
253+
);
254+
}
255+
216256
[Theory]
217257
[InlineData("Foo", true)]
218258
[InlineData("Foo.Bar", true)]
@@ -284,7 +324,7 @@ public void ExceptionThrownIsHandled()
284324
Action<Exception, string, string> customHandler = (ex, name, id) => customHandlerInvoked = true;
285325
component.RenderHtml(exceptionHandler: customHandler);
286326
Assert.True(customHandlerInvoked);
287-
327+
288328
// Custom exception handler set
289329
Exception caughtException = null;
290330
config.Setup(x => x.ExceptionHandler).Returns((ex, name, id) => caughtException = ex);

Diff for: tutorial-code/Views/Home/Index.cshtml

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
submitUrl = Url.Action("AddComment"),
1515
pollInterval = 2000,
1616
})
17-
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.0.0/umd/react.development.js"></script>
18-
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.0.0/umd/react-dom.development.js"></script>
17+
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.4.0/umd/react.development.js"></script>
18+
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.4.0/umd/react-dom.development.js"></script>
1919
<script src="https://cdnjs.cloudflare.com/ajax/libs/prop-types/15.6.0/prop-types.js"></script>
2020
<script src="https://cdnjs.cloudflare.com/ajax/libs/remarkable/1.7.1/remarkable.min.js"></script>
2121
<script src="@Url.Content("~/js/tutorial.jsx")"></script>

0 commit comments

Comments
 (0)