protected PureComponent(TProps props, params Union <ReactElement, string>[] children) { // To ensure that a single "template" (ie. React component) is created per unique class, a static "_reactComponentClasss" dictionary is maintained. If it has no entry // for the current type then this must be the first instantiation of that type and so a component class will be created and added to the dictionary, ready for re-use // by any subsequent component instances. var currentType = ((object)this).GetType(); // Cast to object first in case derived class uses [IgnoreGeneric] - see http://forums.bridge.net/forum/bridge-net-pro/bugs/3343 object reactComponentClass; if (!_reactComponentClasses.TryGetValue(currentType, out reactComponentClass)) { reactComponentClass = ReactComponentClassCreator.CreateClass(this, baseComponent: typeof(PureComponent <TProps>)); _reactComponentClasses[currentType] = reactComponentClass; } // Now that the React component class is certain to have been defined (once per unique C# component class), this instance requires a React element to be created // for it. The internal React mechanism means that the component's constructor will not be executed, which is why ALL configuration options for a component must // be contained within the props. Note: 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. Array createElementArgs = new object[] { reactComponentClass, ComponentPropsHelpers.WrapProps(props) }; if (children != null) { createElementArgs = createElementArgs.Concat(children); } _reactElement = Script.Write <ReactElement>("React.createElement.apply(null, createElementArgs)"); }
protected StatelessComponent(TProps props, params Union <ReactElement, string>[] children) { // 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. Func <TProps, ReactElement> reactStatelessRenderFunction; var currentType = ((object)this).GetType(); // Cast to object first in case derived class uses [IgnoreGeneric] - see http://forums.bridge.net/forum/bridge-net-pro/bugs/3343 if (!_reactStatelessRenderFunctions.TryGetValue(currentType, out reactStatelessRenderFunction)) { reactStatelessRenderFunction = CreateStatelessRenderFunction(); _reactStatelessRenderFunctions[currentType] = 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, ComponentPropsHelpers.WrapProps(props) }; if (children != null) { createElementArgs = Script.Write <Array>("{0}.concat({1})", createElementArgs, children); // Since upgrading from Bridge 1.7.6 to 1.7.9, I'm getting an error that Concat doesn't exist so I'll just do this } _reactElement = Script.Write <ReactElement>("React.createElement.apply(null, {0})", createElementArgs); }
/// <summary> /// This should only be used by the React.DOM factory method overloads - as such, I haven't created separate strongly-typed method signatures for StatelessComponent and PureComponent, /// I've rolled them together by having a single signature that takes an object set. This means that this method could feasibly be called with an object of references without the /// private "_reactElement" property, but no-one should be able to call this anyway so that's very low risk. Note that this won't work with the Component base class, it causes /// React to throw a "Maximum call stack size exceeded" error that I haven't been able to get to the bottom of yet (the ToChildComponentArray extension methods only supported /// StatelessComponent and PureComponent, so I'm ok for now with only supporting DOM factory methods that handle dynamic sets of StatelessComponent and PureComponent but /// not Component) /// </summary> internal static ReactElement[] ToReactElementArray(IEnumerable<object> components) { if (components == null) throw new ArgumentNullException("components"); var componentsArray = components.ToArray(); var reactElements = new ReactElement[componentsArray.Length]; /*@ for (var i = 0; i < componentsArray.length; i++) { reactElements[i] = (componentsArray[i] == null) ? null : componentsArray[i]._reactElement; } */ return reactElements; }
/// <summary> /// This should only be used by the React.DOM factory method overloads - as such, I haven't created separate strongly-typed method signatures for StatelessComponent and PureComponent, /// I've rolled them together by having a single signature that takes an object set. This means that this method could feasibly be called with an object of references without the /// private "_reactElement" property, but no-one should be able to call this anyway so that's very low risk. Note that this won't work with the Component base class, it causes /// React to throw a "Maximum call stack size exceeded" error that I haven't been able to get to the bottom of yet (the ToChildComponentArray extension methods only supported /// StatelessComponent and PureComponent, so I'm ok for now with only supporting DOM factory methods that handle dynamic sets of StatelessComponent and PureComponent but /// not Component) /// </summary> internal static ReactElement[] ToReactElementArray(IEnumerable <object> components) { if (components == null) { throw new ArgumentNullException("components"); } var componentsArray = components.ToArray(); var reactElements = new ReactElement[componentsArray.Length]; /*@ * for (var i = 0; i < componentsArray.length; i++) { * reactElements[i] = (componentsArray[i] == null) ? null : componentsArray[i]._reactElement; * } */ return(reactElements); }
public extern static void Render(ReactElement element, Element container);
public extern static void Render(ReactElement element, Element container, Action callback);