/// <summary> /// Render a React StaticRouter Component with context object. /// Can optionally be provided with a custom context handler to handle the various status codes. /// </summary> /// <param name="htmlHelper">MVC Razor <see cref="IHtmlHelper"/></param> /// <param name="componentName">Name of React Static Router component. Expose component globally to ReactJS.NET</param> /// <param name="props">Props to initialise the component with</param> /// <param name="path">F.x. from Request.Path. Used by React Static Router to determine context and routing.</param> /// <param name="contextHandler">Optional custom context handler, can be used instead of providing a Response object</param> /// <param name="htmlTag">HTML tag to wrap the component in. Defaults to <div></param> /// <param name="containerId">ID to use for the container HTML tag. Defaults to an auto-generated ID</param> /// <param name="clientOnly">Skip rendering server-side and only output client-side initialisation code. Defaults to <c>false</c></param> /// <param name="serverOnly">Skip rendering React specific data-attributes during server side rendering. Defaults to <c>false</c></param> /// <param name="containerClass">HTML class(es) to set on the container tag</param> /// <param name="renderFunctions">Functions to call during component render</param> /// <returns><see cref="IHtmlString"/> containing the rendered markup for provided React Router component</returns> public static IHtmlString ReactRouter <T>( this IHtmlHelper htmlHelper, string componentName, T props, string path = null, string htmlTag = null, string containerId = null, bool clientOnly = false, bool serverOnly = false, string containerClass = null, Action <HttpResponse, RoutingContext> contextHandler = null, IRenderFunctions renderFunctions = null ) { try { var response = htmlHelper.ViewContext.HttpContext.Response; path = path ?? htmlHelper.ViewContext.HttpContext.Request.Path; var reactComponent = Environment.CreateRouterComponent( componentName, props, path, containerId, clientOnly ); if (!string.IsNullOrEmpty(htmlTag)) { reactComponent.ContainerTag = htmlTag; } if (!string.IsNullOrEmpty(containerClass)) { reactComponent.ContainerClass = containerClass; } var executionResult = reactComponent.RenderRouterWithContext(clientOnly, serverOnly, renderFunctions); if (executionResult.Context?.status != null || executionResult.Context?.url != null) { // Use provided contextHandler if (contextHandler != null) { contextHandler(response, executionResult.Context); } // Handle routing context internally else { SetServerResponse.ModifyResponse(executionResult.Context, response); } } return(new HtmlString(executionResult.RenderResult)); } finally { Environment.ReturnEngineToPool(); } }
/// <summary> /// Renders the specified React component /// </summary> /// <typeparam name="T">Type of the props</typeparam> /// <param name="htmlHelper">HTML helper</param> /// <param name="componentName">Name of the component</param> /// <param name="props">Props to initialise the component with</param> /// <param name="htmlTag">HTML tag to wrap the component in. Defaults to <div></param> /// <param name="containerId">ID to use for the container HTML tag. Defaults to an auto-generated ID</param> /// <param name="clientOnly">Skip rendering server-side and only output client-side initialisation code. Defaults to <c>false</c></param> /// <param name="serverOnly">Skip rendering React specific data-attributes, container and client-side initialisation during server side rendering. Defaults to <c>false</c></param> /// <param name="containerClass">HTML class(es) to set on the container tag</param> /// <param name="exceptionHandler">A custom exception handler that will be called if a component throws during a render. Args: (Exception ex, string componentName, string containerId)</param> /// <param name="renderFunctions">Functions to call during component render</param> /// <returns>The component's HTML</returns> public static IHtmlString React <T>( this IHtmlHelper htmlHelper, string componentName, T props, string htmlTag = null, string containerId = null, bool clientOnly = false, bool serverOnly = false, string containerClass = null, Action <Exception, string, string> exceptionHandler = null, IRenderFunctions renderFunctions = null ) { try { var reactComponent = Environment.CreateComponent(componentName, props, containerId, clientOnly, serverOnly); if (!string.IsNullOrEmpty(htmlTag)) { reactComponent.ContainerTag = htmlTag; } if (!string.IsNullOrEmpty(containerClass)) { reactComponent.ContainerClass = containerClass; } return(RenderToString(writer => reactComponent.RenderHtml(writer, clientOnly, serverOnly, exceptionHandler, renderFunctions))); } finally { Environment.ReturnEngineToPool(); } }
/// <summary> /// Render a React StaticRouter Component with context object. /// </summary> /// <param name="renderContainerOnly">Only renders component container. Used for client-side only rendering. Does not make sense in this context but included for consistency</param> /// <param name="renderServerOnly">Only renders the common HTML mark up and not any React specific data attributes. Used for server-side only rendering.</param> /// <param name="renderFunctions">Functions to call during component render</param> /// <returns>Object containing HTML in string format and the React Router context object</returns> public virtual ExecutionResult RenderRouterWithContext( bool renderContainerOnly = false, bool renderServerOnly = false, IRenderFunctions renderFunctions = null ) { var reactRouterFunctions = new ReactRouterFunctions(renderFunctions: renderFunctions); var html = RenderHtml( renderContainerOnly, renderServerOnly, renderFunctions: reactRouterFunctions ); return(new ExecutionResult { RenderResult = html, Context = JsonConvert.DeserializeObject <RoutingContext>(reactRouterFunctions.ReactRouterContext), }); }
/// <summary> /// Constructor. Supports chained calls to multiple render functions by passing in a set of functions that should be called next. /// The functions within the provided RenderFunctions will be called *after* this instance's. /// Supports null as an argument. /// </summary> /// <param name="renderFunctions">The chained render functions to call</param> public EmotionFunctions(IRenderFunctions renderFunctions = null) : base(renderFunctions) { }
public TestRenderFunctions(IRenderFunctions renderFunctions = null) : base(renderFunctions) { }
/// <summary> /// Renders the HTML for this component. This will execute the component server-side and /// return the rendered HTML. /// </summary> /// <param name="writer">The <see cref="T:System.IO.TextWriter" /> to which the content is written</param> /// <param name="renderContainerOnly">Only renders component container. Used for client-side only rendering.</param> /// <param name="renderServerOnly">Only renders the common HTML mark up and not any React specific data attributes. Used for server-side only rendering.</param> /// <param name="exceptionHandler">A custom exception handler that will be called if a component throws during a render. Args: (Exception ex, string componentName, string containerId)</param> /// <param name="renderFunctions">Functions to call during component render</param> /// <returns>HTML</returns> public virtual void RenderHtml(TextWriter writer, bool renderContainerOnly = false, bool renderServerOnly = false, Action <Exception, string, string> exceptionHandler = null, IRenderFunctions renderFunctions = null) { if (!_configuration.UseServerSideRendering) { renderContainerOnly = true; } if (!renderContainerOnly) { EnsureComponentExists(); } var html = string.Empty; if (!renderContainerOnly) { var stringWriter = _sharedStringWriter; if (stringWriter != null) { stringWriter.GetStringBuilder().Clear(); } else { _sharedStringWriter = stringWriter = new StringWriter(new StringBuilder(_serializedProps.Length + 128)); } try { stringWriter.Write(renderServerOnly ? "ReactDOMServer.renderToStaticMarkup(" : "ReactDOMServer.renderToString("); if (renderFunctions != null) { stringWriter.Write(renderFunctions.WrapComponent(GetStringFromWriter(componentInitWriter => WriteComponentInitialiser(componentInitWriter)))); } else { WriteComponentInitialiser(stringWriter); } stringWriter.Write(')'); if (renderFunctions != null) { renderFunctions.PreRender(x => _environment.Execute <string>(x)); html = _environment.Execute <string>(renderFunctions.TransformRenderedHtml(stringWriter.ToString())); renderFunctions.PostRender(x => _environment.Execute <string>(x)); } else { html = _environment.Execute <string>(stringWriter.ToString()); } if (renderServerOnly) { writer.Write(html); return; } } catch (JsException ex) { if (exceptionHandler == null) { exceptionHandler = _configuration.ExceptionHandler; } exceptionHandler(ex, ComponentName, ContainerId); } } writer.Write('<'); writer.Write(ContainerTag); writer.Write(" id=\""); writer.Write(ContainerId); writer.Write('"'); if (!string.IsNullOrEmpty(ContainerClass)) { writer.Write(" class=\""); writer.Write(ContainerClass); writer.Write('"'); } writer.Write('>'); writer.Write(html); writer.Write("</"); writer.Write(ContainerTag); writer.Write('>'); }
/// <summary> /// Renders the HTML for this component. This will execute the component server-side and /// return the rendered HTML. /// </summary> /// <param name="renderContainerOnly">Only renders component container. Used for client-side only rendering.</param> /// <param name="renderServerOnly">Only renders the common HTML mark up and not any React specific data attributes. Used for server-side only rendering.</param> /// <param name="exceptionHandler">A custom exception handler that will be called if a component throws during a render. Args: (Exception ex, string componentName, string containerId)</param> /// <param name="renderFunctions">Functions to call during component render</param> /// <returns>HTML</returns> public virtual string RenderHtml(bool renderContainerOnly = false, bool renderServerOnly = false, Action <Exception, string, string> exceptionHandler = null, IRenderFunctions renderFunctions = null) { return(GetStringFromWriter(renderHtmlWriter => RenderHtml(renderHtmlWriter, renderContainerOnly, renderServerOnly, exceptionHandler, renderFunctions))); }
/// <summary> /// Constructor. Supports chained calls to multiple render functions by passing in a set of functions that should be called next. /// The functions within the provided RenderFunctions will be called *after* this instance's. /// Supports null as an argument. /// </summary> /// <param name="renderFunctions">The chained render functions to call</param> public ReactJssFunctions(IRenderFunctions renderFunctions = null) : base(renderFunctions) { }
/// <summary> /// Constructor. Supports chained calls to multiple render functions by passing in a set of functions that should be called next. /// The functions within the provided RenderFunctions will be called *after* this instance's. /// Supports null as an argument. /// </summary> /// <param name="renderFunctions">The chained render functions to call</param> public ReactHelmetFunctions(IRenderFunctions renderFunctions = null) : base(renderFunctions) { }
/// <summary> /// Constructor. Supports chained calls to multiple render functions by passing in a set of functions that should be called next. /// The functions within the provided RenderFunctions will be called *after* this instance's. /// Supports null as an argument. /// </summary> /// <param name="renderFunctions">The chained render functions to call</param> public StyledComponentsFunctions(IRenderFunctions renderFunctions = null) : base(renderFunctions) { }
public static IHtmlString ReactWithModel <T>(this HtmlHelper htmlHelper, string componentName, T props, string htmlTag = null, string containerId = null, bool clientOnly = false, bool serverOnly = false, string containerClass = null, Action <Exception, string, string> exceptionHandler = null, IRenderFunctions renderFunctions = null) { try { var sb = new StringBuilder(); containerId = componentName.ToLower(); IReactComponent component = Environment.CreateComponent <T>(componentName, props, containerId, clientOnly, serverOnly); if (!string.IsNullOrEmpty(htmlTag)) { component.ContainerTag = htmlTag; } if (!string.IsNullOrEmpty(containerClass)) { component.ContainerClass = containerClass; } var originalResult = component.RenderHtml(clientOnly, serverOnly); var serializedModel = JsonConvert.SerializeObject(props); sb.Append($"<div data-react-component=\"{componentName.ToLower()}\">"); sb.Append(originalResult); sb.Append($"<script>"); sb.Append($"{serializedModel}"); sb.Append("</script>"); sb.Append("</div>"); return(new HtmlString(sb.ToString())); } finally { Environment.ReturnEngineToPool(); } }
/// <summary> /// Constructor. Supports chained calls to multiple render functions by passing in a set of functions that should be called next. /// The functions within the provided RenderFunctions will be called *after* this instance's. /// Supports null as an argument. /// </summary> /// <param name="renderFunctions">The chained render functions to call</param> protected RenderFunctionsBase(IRenderFunctions renderFunctions) { _renderFunctions = renderFunctions; }