public static void Render(ReactElement component, ComponentReady ready) { if (component == null) { throw new ArgumentNullException(nameof(component)); } if (ready == null) { throw new ArgumentNullException(nameof(ready)); } var container = Document.CreateElement("div"); container.Style.Display = Display.None; Window.SetTimeout(() => // Use SetTimeout to ensure that the DOM has updated (that the container has been added) { try { React.Render( new HostComponent( afterUpdate: () => ready(container), wrappedComponent: component ), container ); } catch { container.Remove(); throw; } }); }
protected StatelessComponent(TProps props, params Union <ReactElement, string>[] children) { if (children != null) { if (children.Any(element => element == null)) { throw new ArgumentException("Null reference encountered in children set"); } } // When preparing the "_reactStatelessRenderFunction" reference, a local "reactStatelessRenderFunction" alias is used - this is just so that the JavaScript // code further down (which calls React.createElement) can use this local alias and not have to know how Bridge stores static references var reactStatelessRenderFunction = _reactStatelessRenderFunction; if (reactStatelessRenderFunction == null) { reactStatelessRenderFunction = CreateStatelessRenderFunction(); _reactStatelessRenderFunction = reactStatelessRenderFunction; } // When we pass the props reference to React.createElement, React's internals will rip it apart and reform it - which will cause problems if TProps is a // class with property getters and setters (or any other function) defined on the prototype, since members from the class prototype are not maintained // in this process. Wrapping the props reference into a "value" property gets around this problem, we just have to remember to unwrap them again when // we render. In most cases where children are specified as a params array, we don't want the "children require unique keys" warning from React (you // don't get it if you call DOM.Div(null, "Item1", "Item2"), so we don't want it in most cases here either - to achieve this, we prepare an arguments // array and pass that to React.createElement in an "apply" call. Similar techniques are used in the stateful component. Array createElementArgs = new object[] { reactStatelessRenderFunction, ComponentHelpers <TProps> .WrapProps(props) }; if (children != null) { createElementArgs = createElementArgs.Concat(children); } _reactElement = Script.Write <ReactElement>("React.createElement.apply(null, createElementArgs)"); }
public void TestRenderer() { var render = new ReactRenderer(null); var element = new ReactElement($@" <b class='test1'> <div>eeee</div> <div>eeee</div> <div>eeee {222}</div> </b> "); var dom = new ReactRendererDOMJson(); var sw = Stopwatch.StartNew(); for (int i = 0; i < 100; i++) { render.Render(element, null, dom); } Console.WriteLine(sw.Elapsed); Console.WriteLine(dom.StringWriter.ToString().Length); Console.WriteLine(dom.StringWriter.ToString()); }
public State WithCurrentContainer(ReactElement container) { if (container == null) { throw new ArgumentNullException(nameof(container)); } return((container == CurrentContainerRetrieverIfAny) ? this : new State(container)); }
public NavigateActionMatcher AddFor <T>(ReactElement element) where T : class, INavigationDispatcherAction { if (element == null) { throw new ArgumentNullException("element"); } return(AddFor <T>(action => element)); }
public Props(Action afterUpdate, ReactElement wrappedComponent) { if (afterUpdate == null) { throw new ArgumentNullException(nameof(afterUpdate)); } if (wrappedComponent == null) { throw new ArgumentNullException(nameof(wrappedComponent)); } AfterUpdate = afterUpdate; WrappedComponent = wrappedComponent; }
public Link( UrlDetails url, ReactElement text, bool caseSensitiveUrlMatching = false, Optional <NonBlankTrimmedString> name = new Optional <NonBlankTrimmedString>(), Optional <NonBlankTrimmedString> target = new Optional <NonBlankTrimmedString>(), Optional <ClassName> className = new Optional <ClassName>(), Optional <ClassName> ancestorClassName = new Optional <ClassName>(), Optional <ClassName> selectedClassName = new Optional <ClassName>(), Optional <Action <MouseEvent <Bridge.Html5.HTMLAnchorElement> > > onClick = new Optional <Action <MouseEvent <Bridge.Html5.HTMLAnchorElement> > >(), Optional <IInteractWithBrowserRouting> historyHandlerOverride = new Optional <IInteractWithBrowserRouting>()) : base(new Props(url, text, caseSensitiveUrlMatching, name, target, className, ancestorClassName, selectedClassName, onClick, historyHandlerOverride)) { }
public HostComponent(Action afterUpdate, ReactElement wrappedComponent) : base(new Props(afterUpdate, wrappedComponent)) { }
/// <summary> /// It is common to want to match an Optional Result-or-Errort to one of three ReactElements (a loading state, an error state and a result state) but if all three delegates are specified as anonymous /// lambdas and they all return custom components (that are derived from Bridge.React's Component, PureComponent or StatelessComponent) then the compiler will not be able to infer a common base type /// for them and so type inference on the two-type-argument Match method will fail. Having this method signature gives the compiler a big enough clue that it can work out that common case. In almost /// all methods, null is not an acceptable input but for ReactElement values it IS acceptable and is used to indicate that nothing should be rendered - as such, the handleNoValue value may be null /// and the handleResult and handleError delegates may return null. /// </summary> public static ReactElement Match <T>(this Optional <ResultOrError <T> > source, ReactElement handleNoValue, Func <T, ReactElement> handleResult, Func <NonBlankTrimmedString, ReactElement> handleError) { // Note: handleNoValue is allowed to be null because a null ReactElement is a valid reference (see note in the comment above) if (handleResult == null) { throw new ArgumentNullException(nameof(handleResult)); } if (handleError == null) { throw new ArgumentNullException(nameof(handleError)); } if (!source.IsDefined) { return(handleNoValue); } return(source.Value.Match(handleResult, handleError)); }
private State(ReactElement currentContainerRetrieverIfAny) { CurrentContainerRetrieverIfAny = currentContainerRetrieverIfAny; }