The React framework | React – the Dom node of shallow of Dom principle
Key words: React React-dom React-Reconciler Scheduler
This is the first day of my participation in the Gwen Challenge in November. Check out the details: the last Gwen Challenge in 2021
background
I’ve been using the React stack for a long time, but I haven’t taken the time to think about the underlying logic. By chance, my friends have similar plans, so I decided to study React in a group.
This article is based on many source code analysis articles, add their own understanding, and then output a knowledge comb. If you are also interested, I suggest you take a look at the references, I believe you will also have a different harvest.
This article does not elaborate on the react-Reconciler, Scheduler, Fiber, DOM Diff and Lane in React, but only on the details of how DOM nodes are generated.
directory
- In this paper, the target
- The React architecture
- React-dom background
- Instructions for using react-dom
- React-dom source call chain
- The react – dom dom generated
- Version Comparison (V15.6.2 / V16.14.0 / V17.0.2)
In this paper, the target
We use the React bucket to invoke related apis and life cycles to realize complex business logic, and finally reach the USER’s UI and various I/O operations, and the corresponding UI will also be dynamically updated.
Therefore, how React converts a series of exposed apis into DOM elements of browser pages, the generation process of DOM elements is actually an interesting point, which will also be the core goal of this paper’s analysis. I want to walk you through one of the DOM generation processes.
In a nutshell, the goal of this article: The last step in React is to call the method that produces the actual DOM element.
The React architecture
- Complete architecture diagram (source: 7KMS)
- Brief architecture diagram as I understand it (mainly used for the analysis of this article react-DOM)
React-dom background
React didn’t have ReactDOM before V0.14, all functionality was included in React. React was split into React and ReactDOM since V0.14 (2015-10). Why separate React from ReactDOM? Because of ReactNative. React contains only the core parts common to both Web and Mobile. Dom operations are grouped into the ReactDOM and Mobile operations are included in ReactNative.
ReactDom only does browser-specific or DOM-related operations, such as reactdom.render () and reactdom.finddomNode (). For server-side rendering, reactdom.renderToString () can be used. React not only works with Web pages via ReactDOM, but also with SSR on the server, ReactNative on the mobile, and Electron on the desktop.
Instructions for using react-dom
This package serves as the entry point to the DOM and server renderers for React. It is intended to be paired with the generic React package, which is shipped as react to npm.
In React, the React dom serves two main functions. One is as the startup entry for the entire React and the other is the final DOM rendering exit. This article mainly introduces client and browser environment rendering, not considering SSR server rendering, interested students can refer to the source code of the server part.
- React-dom serves as an entry point: called with the reactdom.render method, as shown below
// react/packages/react-dom/ readme.md
var React = require('react');
var ReactDOM = require('react-dom');
function MyComponent() {
return <div>Hello World</div>;
}
ReactDOM.render(<MyComponent />, node);
Copy the code
- React -dom serves as an exit
- The Final DOM is produced using the Fiber tree generated in the React-Reconciler process (which is considered to be the final tree to render, leaving the whole diff process behind), and the call chain can be referred to in the next section “React-DOM Call Chain for DOM Generation”.
- The React-DOM and the React-Reconciler are strongly coupled, and it can be seen from the source code that there is a mutual call between you and me
- react-dom API
- For general user apis, API exposed in source code readem. md and official documentation:
- Render: The most commonly used method, the implementation portal for the entire React project
- FindDOMNode: If the component is already mounted to the DOM, this method returns the corresponding native DOM element in the browser. This method is useful for reading values from the DOM, such as getting the value of a form field or performing DOM measurements. In most cases, you can bind a ref to a DOM node and avoid using findDOMNode altogether.
- FindDOMNode is an escape hatch that accesses the underlying DOM nodes. In most cases, this approach is not recommended because it breaks the abstract structure of the component. This method is deprecated in strict mode.
- FindDOMNode is only available on components that are already mounted (that is, components that are already placed in the DOM). An exception will be thrown if you try to call an unmounted component (such as findDOMNode() in Render () on a component that has not yet been created).
- FindDOMNode cannot be used for function components.
- UnmountComponentAtNode: Removing a component from the DOM removes its Event Handlers and state. This function does nothing if there are no corresponding mounted components on the specified container. Returns true if the component is removed, false if there are no components to remove.
- You can see all the methods of export from the source code, which in addition to a few methods called by the user, more is to facilitate the test case call
// Export all exports so that they're available in tests. // We can't use export * from in Flow for some reason. export { createPortal, unstable_batchedUpdates, flushSync, __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED, version, findDOMNode, hydrate, render, unmountComponentAtNode, createRoot, createRoot as unstable_createRoot, createBlockingRoot, createBlockingRoot as unstable_createBlockingRoot, unstable_flushControlled, unstable_scheduleHydration, unstable_runWithPriority, unstable_renderSubtreeIntoContainer, unstable_createPortal, unstable_createEventHandle, unstable_isNewReconciler, } from './src/client/ReactDOM'; Copy the code
- For general user apis, API exposed in source code readem. md and official documentation:
React-dom source call chain
In react-DOM, the entry point for rendering the DOM for the first time is the reactdom.render method. In subsequent DOM updates, the entry points that can trigger DOM changes are forceUpdate, setState, useState, useReducer, and so on. These applied upper-level methods connect the React-Reconciler and Scheduler processes by updating the relevant objects, and then produce a renderable Fiber tree for the React-DOM rendering DOM.
Note that the current v17.0.2 release only exposes Legacy’s DOM rendering mode, so you can see that the react-dom code file introduces the render() method from the reactdomLegacy.js file.
- Call chain Part 1
- Call chain Part 2
DOM generation source code
- DOM call method
- This includes creation (insertion) : commitPlacement
- Update (modify attributes) : commitWork
- Delete: commitDeletion
- Matters needing attention:
- Can be seen from the source code is the above three methods is in ReactFiberWorkLoop. Old. Call in js files
- The method is to be realized in the ReactFiberCommitWork. Old. Js file, follow-up may have migrated file
- However, the DOM operations of commitPlacement, commitWork, commitDeletion and further down are not implemented in the reactFiberHostConfig.js file, but introduced from this file. The code example is as follows:
import{...// Omit some code appendChild, appendChildToContainer, insertBefore, insertInContainerBefore, removeChild, removeChildFromContainer, ... // Omit some code } from './ReactFiberHostConfig'; // Note that reactFiberHostconfig. js is in the same directory as ReactFibercommitwork. js, but open reactFiberHostConfig. js as follows: import invariant from 'shared/invariant'; invariant(false.'This module must be shimmed by a specific renderer.'); / / can see and not the above import content, is the real content in the packages/react - dom/SRC/client/ReactDOMHostConfig js directory // ReactFiberHostConfig.js is associated with the contents of reactDomHostconfig. js by rollup package. // If you are interested, debug the implementation in scripts/rollup/forks Copy the code
- React encapsulates the DOM
- React is a direct reference to Element’s native browser-supported object
// The reactdomhostconfig.js file is partially declared as follows // Element, Document, Text, and Comment are all native BOM objects supported by browsers export type Container = Element | Document; export type Instance = Element; export type TextInstance = Text; export type SuspenseInstance = Comment; export type HydratableInstance = Instance | TextInstance | SuspenseInstance; export type PublicInstance = Element | Text; Copy the code
- ClassName Indicates the attribute of the hump
/ / source address: packages/react - dom/SRC/Shared/DOMProperty. Js // React handles the hump attribute as follows: // A few React string attributes have a different name. // This is a mapping from React prop names to the attribute names.[['acceptCharset'.'accept-charset'], ['className'.'class'], ['htmlFor'.'for'], ['httpEquiv'.'http-equiv'], ].forEach(([name, attributeName]) = > { properties[name] = new PropertyInfoRecord( name, STRING, false.// mustUseProperty attributeName, // attributeName null.// attributeNamespace ); }); Copy the code
- DangerouslySetInnerHTML property how to implement
/ / source address: packages/react - dom/SRC/client/setInnerHTML js // This is essentially an assignment to the innerHTML property of the Element object /** * Set the innerHTML property of a node * * @param {DOMElement} node * @param {string} html * @internalc* / const setInnerHTML = createMicrosoftUnsafeLocalFunction(function(node: Element, html: string,) :void { // IE does not have innerHTML for SVG nodes, so instead we inject the // new markup in a temp node and then move the child nodes across into // the target node if(node.namespaceURI === Namespaces.svg && ! ('innerHTML' in node)) { reusableSVGContainer = reusableSVGContainer || document.createElement('div'); reusableSVGContainer.innerHTML = '<svg>' + html + '</svg>'; const svgNode = reusableSVGContainer.firstChild; while (node.firstChild) { node.removeChild(node.firstChild); } while(svgNode.firstChild) { node.appendChild(svgNode.firstChild); }}else{ node.innerHTML = html; }});Copy the code
- In addition to the above two react special processing encapsulation, most of the rest are normal DOM operations, the corresponding source address, can be
react/packages/react-dom/src/client
Found. For example, settextContent. js, reactDomTextarea. js, reactDomSelect. js and so on all handle Text, Textarea, HTMLSelectElement and other objects.
Version Comparison (V15.6.2 / V16.14.0 / V17.0.2)
Only stable versions are considered in version comparison. The latest React stable version is V17.0.2. In order to compare the differences between previous versions, stable versions of larger versions are selected, namely v16.14.0 and V15.6.2
- V17.0.2: Refer to the analysis content of this article
- V16.14.0:
- Call chain reference (initial render/update render) : commitRoot -> commitAllHostEffects -> commitPlacement/commitWork/commitDeletion
- Note: Ignoring the details here, you can see that the main process is similar to v17.0.2, but without some logical decisions
- V15.6.2:
- First render: ReactReconciler mountComponent – >… ->ReactDOMComponent.mountComponent->ReactMount._mountImageIntoNode
- Update rendering: The main logic is in the _updateRenderedComponent method of the source ReactCompositeComponent file. The entire update rendering process needs to be implemented with the DIff process. Update rendering and diff logic are relatively coupled, meaning that DOM updates are basically done during diff, which is quite different from v16.14.0 and V17.0.2.
- Other points to note:
- Although there is no implementation of the Fiber framework in V15.6.2, prototypes of the Fiber and Reconciler architectures similar to those in 16.14.0 exist in the source code, although they were not applied to the stable version when Grunt and GULp were packaged. So in 15.6.2 the entry file should start with the reactdom.js render, which you can see from the entry file after build, and ends with the reactmount.render () method
- The Concurrent mode is also not exposed in the stable version in V17.0.2
- In v15.6.2, the react-dom is generated by calling the gulp task and calling the reactDOM into modules. In SRC/Renderers, it is important to note that this version uses the DI (dependency injection) IOC design pattern, which makes it difficult for many methods to understand the files and objects they are in when reading the source code
- V16.14.0 and V17.0.2 use Lerna package management tools and introduce rollup builds, so the code generation part will be different, so be aware if you are reading the source code
gossip
Thanks to the team at FaceBook for creating React, thanks to the colleagues who have already dissected React for their detailed interpretation, thanks to the partners who have been watching React, and finally thanks to myself.
- Learning experience: In the process of finding out how react-DOM renders the DOM, I feel that there are some experiences that I can sort out, not only for myself to learn other knowledge and feel confused in the future, but also for everyone to think about some perspectives.
- When knowledge diffusion, to remember the starting point, you can make a record of the divergence of knowledge, but must timely review the beginning of what is the starting point, otherwise they will become confused, and can not find the focus.
- After reading two React source code parsing series articles (linked at the end of the article), I can’t remember every detail, but I have a vague idea in my mind. What remains is to go further and further on the details as I did in this article. Then constantly draw their own React knowledge architecture diagrams
- One of the features of the 7KMS article is that many sub-chapters constantly remind readers to review the core package diagram, which is also the React architecture diagram cited in this article. In this regard, my experience is that the knowledge structure diagram drawn by myself should also be polished repeatedly and filled with details. Then, in view of the points I do not understand, I should constantly expand and consolidate them. So when we study, we should also repeatedly series, deepen our understanding.
- Rote memorization can be the beginning, but not the end.
- Knowledge expansion
- Lerna is a management tool for JavaScript projects that contain multiple packages. It is maintained by open source projects such as React and Babel.
- The React V18 release will remove the Reactdom. render method. See the React 18 Replacing Render with createRoot section in Resources for details.
- The React V17.0.2 react-Reconciler’s source code contains XXX.new.js and XXX.old.js, while the stable version uses XXX.old.js, Such as ReactFiberReconciler. New. Js and ReactFiberReconciler. Old. Js, finally use the latter.
- Flow: React still uses flow as a static type checking tool, the same as vue2.x, but vue3.x already uses TypeScript for static type checking.
- The react to the reconciler and react to how the dom dom a type, namely ReactFiberHostConfig. Old. How js and ReactDOMHostConfig. Js objects in how they relate to, Because in ReactFiberHostConfig. Old. Js and there is no corresponding object statement, but in the source cited a lot of “object” does not exist, is through the rollup package to do the mapping relationship.
The resources
- The React lot: github.com/facebook/re…
- React: 7kms. Github. IO /react-illus…
- React Technology Revealed: react.iamkasong.com/
- Why react and React -dom split into two packages? www.zhihu.com/question/33…
- React-v0.14 React-DOM is generated by reactjs.org/blog/2015/1…
- Lerna Chinese website: www.lernajs.cn/
- React 18 Replacing Render with createRoot: github.com/reactwg/rea…
- FLOW IS A STATIC TYPE CHECKER FOR JAVASCRIPT.:flow.org/
- React source analysis: the React, React – dom, the relationship between the React – the reconciler: zhuanlan.zhihu.com/p/266892192
- The React 15.4.2 source interpretation series: segmentfault.com/a/119000001…
Browse creative Commons license agreements
This work adoptsCreative Commons Attribution – Same way share 4.0 International LicenseGrant permission.