ReactDOM

https://github.com/facebook/react/blob/master/packages/react-dom/src/client/ReactDOM.js#L1121

const ReactDOM: Object = {
  createPortal,

  findDOMNode(
    componentOrElement: Element | ?React$Component<any, any>,
  ): null | Element | Text {


    if ((componentOrElement: any).nodeType === ELEMENT_NODE) {
      return (componentOrElement: any);
    }

    const inst = ReactInstanceMap.get(componentOrElement);
    if (inst) {
      return DOMRenderer.findHostInstance(inst);
    }

    if (typeof componentOrElement.render === 'function') {
      invariant(false, 'Unable to find node on an unmounted component.');
    } else {
      invariant(
        false,
        'Element appears to be neither ReactComponent nor DOMNode. Keys: %s',
        Object.keys(componentOrElement),
      );
    }
  },

  hydrate(element: React$Node, container: DOMContainer, callback: ?Function) {
    // TODO: throw or warn if we couldn't hydrate?
    return legacyRenderSubtreeIntoContainer(
      null,
      element,
      container,
      true,
      callback,
    );
  },

  render(
    element: React$Element<any>,
    container: DOMContainer,
    callback: ?Function,
  ) {
    return legacyRenderSubtreeIntoContainer(
      null,
      element,
      container,
      false,
      callback,
    );
  },

   __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: {
    // For TapEventPlugin which is popular in open source
    EventPluginHub,
    // Used by test-utils
    EventPluginRegistry,
    EventPropagators,
    ReactControlledComponent,
    ReactDOMComponentTree,
    ReactDOMEventListener,
  },
}

legacyRenderSubtreeIntoContainer

https://github.com/facebook/react/blob/master/packages/react-dom/src/client/ReactDOM.js#L1041

If root object which the DOM to render does not have internal property _reactRootContainerdoes not exsist, create DOM container from scratch by calling legacyCreateRootFromDOMContainer . If there is Root object container._reactRootContainer, it will return instance of ReactRoot.

function legacyRenderSubtreeIntoContainer(
  parentComponent: ?React$Component<any, any>,
  children: ReactNodeList,
  container: DOMContainer,
  forceHydrate: boolean,
  callback: ?Function,
) {

  let root: Root = (container._reactRootContainer: any);

  if (!root) {

    // Initial mount

    root = container._reactRootContainer = legacyCreateRootFromDOMContainer(
      container,
      forceHydrate,
    );
    if (typeof callback === 'function') {
      const originalCallback = callback;
      callback = function() {
        const instance = DOMRenderer.getPublicRootInstance(root._internalRoot);
        originalCallback.call(instance);
      };
    }


    // Initial mount should not be batched.
    DOMRenderer.unbatchedUpdates(() => {
      if (parentComponent != null) {
        root.legacy_renderSubtreeIntoContainer(
          parentComponent,
          children,
          callback,
        );
      } else {
        root.render(children, callback);
      }
    });

  } else {

    if (typeof callback === 'function') {
      const originalCallback = callback;
      callback = function() {
        const instance = DOMRenderer.getPublicRootInstance(root._internalRoot);
        originalCallback.call(instance);
      };
    }

    // Update
    if (parentComponent != null) {
      root.legacy_renderSubtreeIntoContainer(
        parentComponent,
        children,
        callback,
      );
    } else {
      root.render(children, callback);
    }
  }

  return DOMRenderer.getPublicRootInstance(root._internalRoot);
}

legacyCreateRootFromDOMContainer

https://github.com/facebook/react/blob/master/packages/react-dom/src/client/ReactDOM.js#L996

In case of , this function creates root container for your app.

function legacyCreateRootFromDOMContainer(
  container: DOMContainer,
  forceHydrate: boolean,
): Root {
  const shouldHydrate =
    forceHydrate || shouldHydrateDueToLegacyHeuristic(container);
  // First clear any existing content.
  if (!shouldHydrate) {
    let warned = false;
    let rootSibling;
    while ((rootSibling = container.lastChild)) {
      container.removeChild(rootSibling);
    }
  }
  // Legacy roots are not async by default.
  const isAsync = false;
  return new ReactRoot(container, isAsync, shouldHydrate);
}

ReactRoot

https://github.com/facebook/react/blob/master/packages/react-dom/src/client/ReactDOM.js#L377

ReactRoot is constructor function to create root container and the instance of ReactRoot will have _internalRoot. Interesting things are that the methods render,unmount,legacy_renderSubtreeIntoContainercall DOMRenderer.updateContainer

function and return instance of React.work.

_internalRoot Property contain object returned from DOMRenderer.createContainer https://github.com/facebook/react/blob/master/packages/react-dom/src/client/ReactDOM.js#L378
render Method If parent component exsists, this will be called from legacyRenderSubtreeIntoContainer https://github.com/facebook/react/blob/master/packages/react-dom/src/client/ReactDOM.js#L381
unmount Method https://github.com/facebook/react/blob/master/packages/react-dom/src/client/ReactDOM.js#L397
legacy_renderSubtreeIntoContainer Method If parent component does not exsist, this will be called from legacyRenderSubtreeIntoContainer https://github.com/facebook/react/blob/master/packages/react-dom/src/client/ReactDOM.js#L410
createBatch Method https://github.com/facebook/react/blob/master/packages/react-dom/src/client/ReactDOM.js#L429
function ReactRoot(container: Container, isAsync: boolean, hydrate: boolean) {
  const root = DOMRenderer.createContainer(container, isAsync, hydrate);
  this._internalRoot = root;
}

/**
 * render
 */

ReactRoot.prototype.render = function(
  children: ReactNodeList,
  callback: ?() => mixed,
): Work {
  const root = this._internalRoot;
  const work = new ReactWork();
  callback = callback === undefined ? null : callback;
  if (__DEV__) {
    warnOnInvalidCallback(callback, 'render');
  }
  if (callback !== null) {
    work.then(callback);
  }
  DOMRenderer.updateContainer(children, root, null, work._onCommit);
  return work;
};


/**
 * unmount
 */

ReactRoot.prototype.unmount = function(callback: ?() => mixed): Work {
  const root = this._internalRoot;
  const work = new ReactWork();
  callback = callback === undefined ? null : callback;
  if (__DEV__) {
    warnOnInvalidCallback(callback, 'render');
  }
  if (callback !== null) {
    work.then(callback);
  }
  DOMRenderer.updateContainer(null, root, null, work._onCommit);
  return work;
};


/**
 * legacy_renderSubtreeIntoContainer
 */

ReactRoot.prototype.legacy_renderSubtreeIntoContainer = function(
  parentComponent: ?React$Component<any, any>,
  children: ReactNodeList,
  callback: ?() => mixed,
): Work {
  const root = this._internalRoot;
  const work = new ReactWork();
  callback = callback === undefined ? null : callback;
  if (__DEV__) {
    warnOnInvalidCallback(callback, 'render');
  }
  if (callback !== null) {
    work.then(callback);
  }
  DOMRenderer.updateContainer(children, root, parentComponent, work._onCommit);
  return work;
};


/**
 * createBatch
 */

ReactRoot.prototype.createBatch = function(): Batch {
  const batch = new ReactBatch(this);
  const expirationTime = batch._expirationTime;

  const internalRoot = this._internalRoot;
  const firstBatch = internalRoot.firstBatch;
  if (firstBatch === null) {
    internalRoot.firstBatch = batch;
    batch._next = null;
  } else {
    // Insert sorted by expiration time then insertion order
    let insertAfter = null;
    let insertBefore = firstBatch;
    while (
      insertBefore !== null &&
      insertBefore._expirationTime <= expirationTime
    ) {
      insertAfter = insertBefore;
      insertBefore = insertBefore._next;
    }
    batch._next = insertBefore;
    if (insertAfter !== null) {
      insertAfter._next = batch;
    }
  }

  return batch;
};

DOMRenderer

https://github.com/facebook/react/blob/master/packages/react-dom/src/client/ReactDOM.js#L506

ReactFiberReconciler is another library and return new object. https://github.com/facebook/react/blob/master/packages/react-reconciler/src/ReactFiberReconciler.js#L412. The object passed to ReactFiberReconciler is config.

const DOMRenderer = ReactFiberReconciler({
  getRootHostContext(rootContainerInstance: Container): HostContext {
    let type;
    let namespace;
    const nodeType = rootContainerInstance.nodeType;
    switch (nodeType) {
      case DOCUMENT_NODE:
      case DOCUMENT_FRAGMENT_NODE: {
        type = nodeType === DOCUMENT_NODE ? '#document' : '#fragment';
        let root = (rootContainerInstance: any).documentElement;
        namespace = root ? root.namespaceURI : getChildNamespace(null, '');
        break;
      }
      default: {
        const container: any =
          nodeType === COMMENT_NODE
            ? rootContainerInstance.parentNode
            : rootContainerInstance;
        const ownNamespace = container.namespaceURI || null;
        type = container.tagName;
        namespace = getChildNamespace(ownNamespace, type);
        break;
      }
    }

    return namespace;
  },

  getChildHostContext(
    parentHostContext: HostContext,
    type: string,
  ): HostContext {

    const parentNamespace = ((parentHostContext: any): HostContextProd);
    return getChildNamespace(parentNamespace, type);
  },

  getPublicInstance(instance) {
    return instance;
  },

  prepareForCommit(): void {
    eventsEnabled = ReactBrowserEventEmitter.isEnabled();
    selectionInformation = ReactInputSelection.getSelectionInformation();
    ReactBrowserEventEmitter.setEnabled(false);
  },

  resetAfterCommit(): void {
    ReactInputSelection.restoreSelection(selectionInformation);
    selectionInformation = null;
    ReactBrowserEventEmitter.setEnabled(eventsEnabled);
    eventsEnabled = null;
  },

  createInstance(
    type: string,
    props: Props,
    rootContainerInstance: Container,
    hostContext: HostContext,
    internalInstanceHandle: Object,
  ): Instance {
    let parentNamespace: string;

    const domElement: Instance = createElement(
      type,
      props,
      rootContainerInstance,
      parentNamespace,
    );
    precacheFiberNode(internalInstanceHandle, domElement);
    updateFiberProps(domElement, props);
    return domElement;
  },

  appendInitialChild(
    parentInstance: Instance,
    child: Instance | TextInstance,
  ): void {
    parentInstance.appendChild(child);
  },

  finalizeInitialChildren(
    domElement: Instance,
    type: string,
    props: Props,
    rootContainerInstance: Container,
  ): boolean {
    setInitialProperties(domElement, type, props, rootContainerInstance);
    return shouldAutoFocusHostComponent(type, props);
  },

  prepareUpdate(
    domElement: Instance,
    type: string,
    oldProps: Props,
    newProps: Props,
    rootContainerInstance: Container,
    hostContext: HostContext,
  ): null | Array<mixed> {

    return diffProperties(
      domElement,
      type,
      oldProps,
      newProps,
      rootContainerInstance,
    );
  },

  shouldSetTextContent(type: string, props: Props): boolean {
    return (
      type === 'textarea' ||
      typeof props.children === 'string' ||
      typeof props.children === 'number' ||
      (typeof props.dangerouslySetInnerHTML === 'object' &&
        props.dangerouslySetInnerHTML !== null &&
        typeof props.dangerouslySetInnerHTML.__html === 'string')
    );
  },

  shouldDeprioritizeSubtree(type: string, props: Props): boolean {
    return !!props.hidden;
  },

  createTextInstance(
    text: string,
    rootContainerInstance: Container,
    hostContext: HostContext,
    internalInstanceHandle: Object,
  ): TextInstance {

    const textNode: TextInstance = createTextNode(text, rootContainerInstance);
    precacheFiberNode(internalInstanceHandle, textNode);
    return textNode;
  },

  now: ReactDOMFrameScheduling.now,

  mutation: {
    commitMount(
      domElement: Instance,
      type: string,
      newProps: Props,
      internalInstanceHandle: Object,
    ): void {
      // Despite the naming that might imply otherwise, this method only
      // fires if there is an `Update` effect scheduled during mounting.
      // This happens if `finalizeInitialChildren` returns `true` (which it
      // does to implement the `autoFocus` attribute on the client). But
      // there are also other cases when this might happen (such as patching
      // up text content during hydration mismatch). So we'll check this again.
      if (shouldAutoFocusHostComponent(type, newProps)) {
        ((domElement: any):
          | HTMLButtonElement
          | HTMLInputElement
          | HTMLSelectElement
          | HTMLTextAreaElement).focus();
      }
    },

    commitUpdate(
      domElement: Instance,
      updatePayload: Array<mixed>,
      type: string,
      oldProps: Props,
      newProps: Props,
      internalInstanceHandle: Object,
    ): void {
      // Update the props handle so that we know which props are the ones with
      // with current event handlers.
      updateFiberProps(domElement, newProps);
      // Apply the diff to the DOM node.
      updateProperties(domElement, updatePayload, type, oldProps, newProps);
    },

    resetTextContent(domElement: Instance): void {
      setTextContent(domElement, '');
    },

    commitTextUpdate(
      textInstance: TextInstance,
      oldText: string,
      newText: string,
    ): void {
      textInstance.nodeValue = newText;
    },

    appendChild(
      parentInstance: Instance,
      child: Instance | TextInstance,
    ): void {
      parentInstance.appendChild(child);
    },

    appendChildToContainer(
      container: Container,
      child: Instance | TextInstance,
    ): void {
      if (container.nodeType === COMMENT_NODE) {
        (container.parentNode: any).insertBefore(child, container);
      } else {
        container.appendChild(child);
      }
    },

    insertBefore(
      parentInstance: Instance,
      child: Instance | TextInstance,
      beforeChild: Instance | TextInstance,
    ): void {
      parentInstance.insertBefore(child, beforeChild);
    },

    insertInContainerBefore(
      container: Container,
      child: Instance | TextInstance,
      beforeChild: Instance | TextInstance,
    ): void {
      if (container.nodeType === COMMENT_NODE) {
        (container.parentNode: any).insertBefore(child, beforeChild);
      } else {
        container.insertBefore(child, beforeChild);
      }
    },

    removeChild(
      parentInstance: Instance,
      child: Instance | TextInstance,
    ): void {
      parentInstance.removeChild(child);
    },

    removeChildFromContainer(
      container: Container,
      child: Instance | TextInstance,
    ): void {
      if (container.nodeType === COMMENT_NODE) {
        (container.parentNode: any).removeChild(child);
      } else {
        container.removeChild(child);
      }
    },
  },

  hydration: {
    canHydrateInstance(
      instance: Instance | TextInstance,
      type: string,
      props: Props,
    ): null | Instance {
      if (
        instance.nodeType !== ELEMENT_NODE ||
        type.toLowerCase() !== instance.nodeName.toLowerCase()
      ) {
        return null;
      }
      // This has now been refined to an element node.
      return ((instance: any): Instance);
    },

    canHydrateTextInstance(
      instance: Instance | TextInstance,
      text: string,
    ): null | TextInstance {
      if (text === '' || instance.nodeType !== TEXT_NODE) {
        // Empty strings are not parsed by HTML so there won't be a correct match here.
        return null;
      }
      // This has now been refined to a text node.
      return ((instance: any): TextInstance);
    },

    getNextHydratableSibling(
      instance: Instance | TextInstance,
    ): null | Instance | TextInstance {
      let node = instance.nextSibling;
      // Skip non-hydratable nodes.
      while (
        node &&
        node.nodeType !== ELEMENT_NODE &&
        node.nodeType !== TEXT_NODE
      ) {
        node = node.nextSibling;
      }
      return (node: any);
    },

    getFirstHydratableChild(
      parentInstance: Container | Instance,
    ): null | Instance | TextInstance {
      let next = parentInstance.firstChild;
      // Skip non-hydratable nodes.
      while (
        next &&
        next.nodeType !== ELEMENT_NODE &&
        next.nodeType !== TEXT_NODE
      ) {
        next = next.nextSibling;
      }
      return (next: any);
    },

    hydrateInstance(
      instance: Instance,
      type: string,
      props: Props,
      rootContainerInstance: Container,
      hostContext: HostContext,
      internalInstanceHandle: Object,
    ): null | Array<mixed> {
      precacheFiberNode(internalInstanceHandle, instance);
      // TODO: Possibly defer this until the commit phase where all the events
      // get attached.
      updateFiberProps(instance, props);
      let parentNamespace: string;
      if (__DEV__) {
        const hostContextDev = ((hostContext: any): HostContextDev);
        parentNamespace = hostContextDev.namespace;
      } else {
        parentNamespace = ((hostContext: any): HostContextProd);
      }
      return diffHydratedProperties(
        instance,
        type,
        props,
        parentNamespace,
        rootContainerInstance,
      );
    },

    hydrateTextInstance(
      textInstance: TextInstance,
      text: string,
      internalInstanceHandle: Object,
    ): boolean {
      precacheFiberNode(internalInstanceHandle, textInstance);
      return diffHydratedText(textInstance, text);
    },

    didNotMatchHydratedContainerTextInstance(
      parentContainer: Container,
      textInstance: TextInstance,
      text: string,
    ) {
      if (__DEV__) {
        warnForUnmatchedText(textInstance, text);
      }
    },

    didNotMatchHydratedTextInstance(
      parentType: string,
      parentProps: Props,
      parentInstance: Instance,
      textInstance: TextInstance,
      text: string,
    ) {
      if (__DEV__ && parentProps[SUPPRESS_HYDRATION_WARNING] !== true) {
        warnForUnmatchedText(textInstance, text);
      }
    },

    didNotHydrateContainerInstance(
      parentContainer: Container,
      instance: Instance | TextInstance,
    ) {
      if (__DEV__) {
        if (instance.nodeType === 1) {
          warnForDeletedHydratableElement(parentContainer, (instance: any));
        } else {
          warnForDeletedHydratableText(parentContainer, (instance: any));
        }
      }
    },

    didNotHydrateInstance(
      parentType: string,
      parentProps: Props,
      parentInstance: Instance,
      instance: Instance | TextInstance,
    ) {
      if (__DEV__ && parentProps[SUPPRESS_HYDRATION_WARNING] !== true) {
        if (instance.nodeType === 1) {
          warnForDeletedHydratableElement(parentInstance, (instance: any));
        } else {
          warnForDeletedHydratableText(parentInstance, (instance: any));
        }
      }
    },

    didNotFindHydratableContainerInstance(
      parentContainer: Container,
      type: string,
      props: Props,
    ) {
      if (__DEV__) {
        warnForInsertedHydratedElement(parentContainer, type, props);
      }
    },

    didNotFindHydratableContainerTextInstance(
      parentContainer: Container,
      text: string,
    ) {
      if (__DEV__) {
        warnForInsertedHydratedText(parentContainer, text);
      }
    },

    didNotFindHydratableInstance(
      parentType: string,
      parentProps: Props,
      parentInstance: Instance,
      type: string,
      props: Props,
    ) {
      if (__DEV__ && parentProps[SUPPRESS_HYDRATION_WARNING] !== true) {
        warnForInsertedHydratedElement(parentInstance, type, props);
      }
    },

    didNotFindHydratableTextInstance(
      parentType: string,
      parentProps: Props,
      parentInstance: Instance,
      text: string,
    ) {
      if (__DEV__ && parentProps[SUPPRESS_HYDRATION_WARNING] !== true) {
        warnForInsertedHydratedText(parentInstance, text);
      }
    },
  },

  scheduleDeferredCallback: ReactDOMFrameScheduling.rIC,
  cancelDeferredCallback: ReactDOMFrameScheduling.cIC,
});

ReactGenericBatching.injection.injectRenderer(DOMRenderer);

results matching ""

    No results matching ""