001package react4j.dom; 002 003import akasha.Element; 004import arez.Arez; 005import arez.ArezContext; 006import javax.annotation.Nonnull; 007import javax.annotation.Nullable; 008import jsinterop.annotations.JsFunction; 009import jsinterop.annotations.JsMethod; 010import jsinterop.annotations.JsOverlay; 011import jsinterop.annotations.JsPackage; 012import jsinterop.annotations.JsType; 013import react4j.React; 014import react4j.ReactElement; 015import react4j.ReactNode; 016 017/** 018 * Core interface into React DOM library. 019 */ 020@JsType( isNative = true, namespace = JsPackage.GLOBAL ) 021public class ReactDOM 022{ 023 private ReactDOM() 024 { 025 } 026 027 /** 028 * Interface for performing an action inside batch. 029 */ 030 @FunctionalInterface 031 @JsFunction 032 public interface BatchedUpdatesFn 033 { 034 /** 035 * Perform action while batching react changes. 036 * 037 * @throws Throwable if an error occurred. 038 */ 039 void call() 040 throws Throwable; 041 } 042 043 /** 044 * Interface for performing an action on render complete. 045 */ 046 @FunctionalInterface 047 @JsFunction 048 public interface RenderCallbackFn 049 { 050 /** 051 * Perform action on render complete. 052 */ 053 void call(); 054 } 055 056 @JsOverlay 057 @Nonnull 058 public static ReactRoot createRoot( @Nonnull final Element container ) 059 { 060 return unstable_createRoot( container ); 061 } 062 063 @Nonnull 064 private static native ReactRoot unstable_createRoot( @Nonnull Element container ); 065 066 /** 067 * Portals provide a first-class way to render children into a DOM node that exists outside the DOM hierarchy 068 * of the parent component. 069 * 070 * <p>Even though a portal can be anywhere in the DOM tree, it behaves like a normal React child in every 071 * other way. Features like context work exactly the same regardless of whether the child is a portal, as 072 * the portal still exists in the React tree regardless of position in the DOM tree.</p> 073 * 074 * <p>This includes event bubbling. An event fired from inside a portal will propagate to ancestors in 075 * the containing React tree, even if those elements are not ancestors in the DOM tree.</p> 076 * 077 * @param children the react node to render. 078 * @param container the DOM element to render into. 079 * @return the new portal. 080 */ 081 public static native ReactPortal createPortal( @Nonnull ReactNode children, @Nonnull Element container ); 082 083 /** 084 * Render a React element into the DOM in the supplied container. 085 * 086 * <p>If the React element was previously rendered into container, this will perform an update on it and only 087 * mutate the DOM as necessary to reflect the latest React element.</p> 088 * 089 * <p>If the optional callback is provided, it will be executed after the component is rendered or updated.</p> 090 * 091 * @param node the react node to render. 092 * @param container the DOM element to render into. 093 * @param onUpdate the callback invoked when rendering is complete. 094 * @return a reference to the created React Component, DOM Node, Portal or null (stateless components). 095 */ 096 @Nullable 097 @JsOverlay 098 public static Object render( @Nonnull final ReactNode node, 099 @Nonnull final Element container, 100 @Nullable final RenderCallbackFn onUpdate ) 101 { 102 return _render( React.shouldCheckInvariants() ? ReactElement.createStrictMode( node ) : node, container, onUpdate ); 103 } 104 105 @Nullable 106 @JsMethod( name = "render" ) 107 private static native Object _render( @Nonnull ReactNode node, 108 @Nonnull Element container, 109 @Nullable RenderCallbackFn onUpdate ); 110 111 /** 112 * Render a React element into the DOM in the supplied container. 113 * 114 * <p>If the React element was previously rendered into container, this will perform an update on it and only 115 * mutate the DOM as necessary to reflect the latest React element.</p> 116 * 117 * @param node the react node to render. 118 * @param container the DOM element to render into. 119 * @return a reference to the created React Component, DOM Node, Portal or null (stateless components). 120 * @see #render(ReactNode, Element, RenderCallbackFn) 121 */ 122 @Nullable 123 @JsOverlay 124 public static Object render( @Nonnull ReactNode node, @Nonnull Element container ) 125 { 126 return render( node, container, null ); 127 } 128 129 /** 130 * Remove a mounted React component from the DOM and clean up its event handlers and state. If 131 * no component was mounted in the container, calling this function does nothing. 132 * 133 * @param container the DOM container containing the react component to unmount 134 * @return true if a component was unmounted and false if there was no component to unmount. 135 */ 136 public static native boolean unmountComponentAtNode( @Nonnull Element container ); 137 138 /** 139 * Batch all state updates within the action. 140 * This is currently an unstable API within the React 16, mostly because it is only useful when called 141 * outside an event handler (i.e. from network code) and because it is likely to be enabled by default 142 * in a later version of React. 143 * 144 * @param action the action where all state updates are batched. 145 */ 146 @JsOverlay 147 public static void batchedUpdates( @Nonnull final BatchedUpdatesFn action ) 148 { 149 unstable_batchedUpdates( action ); 150 } 151 152 /** 153 * Register an task interceptor on the current Arez context that ensures any view updates are batched. 154 */ 155 @JsOverlay 156 public static void registerBatchedArezTaskInterceptor() 157 { 158 registerBatchedArezTaskInterceptor( Arez.context() ); 159 } 160 161 /** 162 * Register an task interceptor that ensures any view updates are batched. 163 * 164 * @param context the context to add interceptor to. 165 */ 166 @JsOverlay 167 public static void registerBatchedArezTaskInterceptor( @Nonnull final ArezContext context ) 168 { 169 context.setTaskInterceptor( new BatchingTaskInterceptor() ); 170 } 171 172 /** 173 * The native method with the unstable prefix. 174 * 175 * @param action the action where all state updates are batched. 176 */ 177 @JsMethod 178 private static native void unstable_batchedUpdates( @Nonnull BatchedUpdatesFn action ); 179}