Skip to content

Commit

Permalink
Merge pull request #13 from fortedigital/9-serialization-of-props-to-…
Browse files Browse the repository at this point in the history
…json-is-happening-twice

Add json props to html as script tag. Hydrate based of props from scr…
  • Loading branch information
pawil31 authored Apr 14, 2023
2 parents 47d17b7 + 520c96d commit 46d7358
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 26 deletions.
6 changes: 5 additions & 1 deletion Forte.React.AspNetCore/React/Component.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@ namespace Forte.React.AspNetCore.React;

internal class Component
{

public string Name { get; }
public object Props { get; }
public string ContainerId { get; } = Guid.NewGuid().ToString("n")[..8];
public string ContainerId { get; }
public string JsonContainerId { get; }

public Component(string name, object props)
{
Name = name;
Props = props;
ContainerId = Guid.NewGuid().ToString("n")[..8];
JsonContainerId = ContainerId + "-json";
}
}
24 changes: 9 additions & 15 deletions Forte.React.AspNetCore/React/ReactService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,17 @@ public class ReactService : IReactService
private readonly ReactConfiguration _config;
private const string RenderToStringCacheIdentifier = nameof(RenderToStringAsync);

private readonly JsonSerializerOptions _serializeOptions;

public static IReactService Create(IServiceProvider serviceProvider)
{
return new ReactService(
serviceProvider.GetRequiredService<INodeJSService>(),
serviceProvider.GetRequiredService<ReactConfiguration>(),
serviceProvider.GetRequiredService<IOptions<ReactJsonSerializerOptions>>());
serviceProvider.GetRequiredService<ReactConfiguration>());
}

private ReactService(INodeJSService nodeJsService, ReactConfiguration config,
IOptions<ReactJsonSerializerOptions> serializeOptions)
private ReactService(INodeJSService nodeJsService, ReactConfiguration config)
{
_nodeJsService = nodeJsService;
_config = config;
_serializeOptions = serializeOptions.Value.Options;
}

public async Task<string> RenderToStringAsync(string componentName, object props)
Expand All @@ -53,7 +48,7 @@ public async Task<string> RenderToStringAsync(string componentName, object props
return WrapRenderedStringComponent(string.Empty, component);
}

var args = new[] { componentName, props, _config.ScriptUrls };
var args = new[] { componentName, component.JsonContainerId, props, _config.ScriptUrls };

var (success, cachedResult) =
await _nodeJsService.TryInvokeFromCacheAsync<string>(RenderToStringCacheIdentifier, args: args);
Expand All @@ -73,7 +68,8 @@ Stream ModuleFactory()
$"Can not get manifest resource stream with name - {renderToStringScriptManifestName}");
}

var result = await _nodeJsService.InvokeFromStreamAsync<string>(ModuleFactory,
await using var stream = ModuleFactory();
var result = await _nodeJsService.InvokeFromStreamAsync<string>(stream,
RenderToStringCacheIdentifier,
args: args);

Expand All @@ -99,14 +95,12 @@ public string GetInitJavascript()
}

private static string GetElementById(string containerId)
{
return $"document.getElementById(\"{containerId}\")";
}
=> $"document.getElementById(\"{containerId}\")";


private string CreateElement(Component component)
{
return $"React.createElement({component.Name}, {JsonSerializer.Serialize(component.Props, _serializeOptions)})";
}
=>
$"React.createElement({component.Name}, JSON.parse(document.getElementById(\"{component.JsonContainerId}\").textContent))";


private string Render(Component component)
Expand Down
31 changes: 21 additions & 10 deletions Forte.React.AspNetCore/renderToString.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
module.exports = (callback, componentName, props = {}, scriptFiles) => {
scriptFiles.forEach((scriptFile) => { require(scriptFile) });
module.exports = (
callback,
componentName,
jsonContainerId,
props = {},
scriptFiles
) => {
scriptFiles.forEach((scriptFile) => {
require(scriptFile);
});
const component = global[componentName];

const component = global[componentName];
const ReactDOMServer = global["ReactDOMServer"];
const React = global["React"];
const element = React.createElement(component, props);

const ReactDOMServer = global["ReactDOMServer"];
const React = global["React"];
const element = React.createElement(component, props);
const componentHtml = `${ReactDOMServer.renderToString(element)}`;
const jsonHtml = `<script id="${jsonContainerId}" type="json">${JSON.stringify(
props
)}</script>`;
const result = componentHtml + jsonHtml;

const result = ReactDOMServer.renderToString(element);

callback(null /* error */, result /* result */);
}
callback(null /* error */, result /* result */);
};

0 comments on commit 46d7358

Please sign in to comment.