Uncaught Typeerror: Cannot Read Property 'expirationtime' of Undefined React-dom
May your hereafter be pure and vivid, like your lovely eyes at the moment. ——Pushkin
- The official account of WeChatJavaScript total stack》
- Dig for gilt《Primary of oneness》
- Bilibili 《Chief of oneness》
- Source GitHub address: https://github.com/Walker-Leee/react-larn-code-v16.12.0
We've explored the origin of species, and we've imagined where we're going in the future. A plan, it also has life and decease, more than than reincarnation.
React
The living life ofReactDOM.render
This process will reserve a lot of necessities for its life. We volition follow this clue to explore baby likeReact
At the offset of application.
We summarize the performance of update creation into the following two scenarios
- ReactDOM.render
- setState
- forceUpdate
ReactDom.render
The contents are connected in series, and a movie is used to embrace information technology.
First of allreact-dom/client/ReactDOM
In terms ofReactDOM
It includes well-known methods, unstable methods, and methods that are near to be abandoned.
const ReactDOM: Object = { createPortal, // Legacy findDOMNode, hydrate, return, unstable_renderSubtreeIntoContainer, unmountComponentAtNode, // Temporary allonym since we already shipped React 16 RC with information technology. // TODO: remove in React 17. unstable_createPortal(...args) { // ... render createPortal(...args); }, unstable_batchedUpdates: batchedUpdates, flushSync: flushSync, __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: { // ... }, };
The methods hither are all from./ReactDOMLegacy
,render
The method definition is very uncomplicated. As nosotros often utilize, the first parameter is the component, the second parameter is the DOM node to which the component is to be mounted, and the third parameter is the callback office.
export function render( element: React$Element<any>, container: DOMContainer, callback: ?Function, ) { // ... return legacyRenderSubtreeIntoContainer( naught, element, container, fake, callback, ); } role legacyRenderSubtreeIntoContainer( parentComponent: ?React$Component<whatever, any>, children: ReactNodeList, container: DOMContainer, forceHydrate: boolean, callback: ?Office, ) { // TODO: Without `whatever` type, Flow says "Property cannot be accessed on any // member of intersection type." Whyyyyyy. let root: RootType = (container._reactRootContainer: any); let fiberRoot; if (!root) { // Initial mount root = container._reactRootContainer = legacyCreateRootFromDOMContainer( container, forceHydrate, ); fiberRoot = root._internalRoot; if (typeof callback === 'function') { const originalCallback = callback; callback = function() { const instance = getPublicRootInstance(fiberRoot); originalCallback.call(instance); }; } //For the first rendering, updates are not marked equally batched unbatchedUpdates(() => { updateContainer(children, fiberRoot, parentComponent, callback); }); } else { fiberRoot = root._internalRoot; if (typeof callback === 'part') { const originalCallback = callback; callback = function() { const instance = getPublicRootInstance(fiberRoot); originalCallback.call(instance); }; } // Update updateContainer(children, fiberRoot, parentComponent, callback); } return getPublicRootInstance(fiberRoot); }
This code is not difficult to find, callReactDOM.render
When theparentComponent
It is zippo, and the get-go rendering volition not update the batch strategy, simply need to exist completed as soon as possible. (follow upwards of batch updates)
It is not hard to meet from this office of the source code,return
andcreateProtal
The root node is created through the DOM container. The source code is as follows
part legacyCreateRootFromDOMContainer( container: DOMContainer, forceHydrate: boolean, ): RootType { const shouldHydrate = forceHydrate || shouldHydrateDueToLegacyHeuristic(container); // Kickoff clear whatever existing content. if (!shouldHydrate) { allow warned = fake; let rootSibling; while ((rootSibling = container.lastChild)) { // ... container.removeChild(rootSibling); } } return createLegacyRoot( container, shouldHydrate ? { hydrate: truthful, } : undefined, ); }
createLegacyRoot
Defined in./ReactDOMRoot
Specifies the DOM container created and some option settings, and eventually returns aReactDOMBlockingRoot
。
export function createLegacyRoot( container: DOMContainer, options?: RootOptions, ): RootType { return new ReactDOMBlockingRoot(container, LegacyRoot, options); } function ReactDOMBlockingRoot( container: DOMContainer, tag: RootTag, options: void | RootOptions, ) { this._internalRoot = createRootImpl(container, tag, options); } function createRootImpl( container: DOMContainer, tag: RootTag, options: void | RootOptions, ) { // Tag is either LegacyRoot or Concurrent Root // ... const root = createContainer(container, tag, hydrate, hydrationCallbacks); // ... return root; }
The key bespeak is that the method eventually calls thecreateContainer
To create root, which creates theFiberRoot
This object plays a very important function in the subsequent update scheduling process. We will introduce the update scheduling content in detail.
In this section, we see two methods: createcontainer and updatecontainer, both fromreact-reconciler/inline.dom
, finally divers in`react-reconciler/src/ReactFiberReconciler
。 The creation method is very simple, equally follows
consign role createContainer( containerInfo: Container, tag: RootTag, hydrate: boolean, hydrationCallbacks: goose egg | SuspenseHydrationCallbacks, ): OpaqueRoot { return createFiberRoot(containerInfo, tag, hydrate, hydrationCallbacks); }
Nosotros continue to await down, then we can seeupdateContainer
Method, which defines the update related operations, and i of the most of import points isexpirationTimeThe expiration time is direct translated into Chinese. Let's think about it. Why is the expiration time hither? What is the meaning of this expiration? How is the expiration time calculated? Going downward, we tin can see,computeExpirationForFiber
Method is used to calculate the expiration time. Nosotros put the source code fragment hither first.
export office updateContainer( chemical element: ReactNodeList, container: OpaqueRoot, parentComponent: ?React$Component<any, whatsoever>, callback: ?Office, ): ExpirationTime { const electric current = container.current; const currentTime = requestCurrentTimeForUpdate(); // ... const suspenseConfig = requestCurrentSuspenseConfig(); const expirationTime = computeExpirationForFiber( currentTime, current, suspenseConfig, ); // ... const context = getContextForSubtree(parentComponent); if (container.context === cipher) { container.context = context; } else { container.pendingContext = context; } // ... const update = createUpdate(expirationTime, suspenseConfig); // Caution: React DevTools currently depends on this holding // being called "element". update.payload = {chemical element}; callback = callback === undefined ? null : callback; if (callback !== nix) { warningWithoutStack( typeof callback === 'function', 'render(...): Expected the last optional `callback` argument to be a ' + 'function. Instead received: %s.', callback, ); update.callback = callback; } enqueueUpdate(electric current, update); scheduleWork(current, expirationTime); render expirationTime; }
After calculating the update timeout, the update object is createdcreateUpdate
And then bind the element to the update object, and if there is a callback function, bind the callback function to the update object as well. After the update object is created, add the update to the updatequeue. For the data structure of update and updatequeue, see the previous section. At this signal, job scheduling begins.
Fix state and forceupdate
These two methods are bound in the file in which we originally divers react, which is defined inreact/src/ReactBaseClasses
As follows
Component.prototype.setState = office(partialState, callback) { // ... this.updater.enqueueSetState(this, partialState, callback, 'setState'); }; Component.image.forceUpdate = role(callback) { this.updater.enqueueForceUpdate(this, callback, 'forceUpdate'); };
This is why it is easy to expand react native on the basis of react, because react only makes some specifications and structure settings, and the specific implementation is in react DOM or react native, so as to attain the platform adjustability.
Update and use of class componentsthis.setState
We are familiar with this API for a long time. For the update and cosmos of object components, definereact-reconciler/src/ReactFiberClassComponent.js
The classcomponentupdater object defines theenqueueSetState
AndenqueueReplaceState
as well every bitenqueueForceUpdate
Object method, observe the ii methods and find that the difference isenqueueReplaceState
andenqueueForceUpdate
A tag is spring to the created update object. The blazon used to mark the update isReplaceState
neverthelessForceUpdate
Let's take a wait at the code fragment.
const classComponentUpdater = { isMounted, enqueueSetState(inst, payload, callback) { const fiber = getInstance(inst); const currentTime = requestCurrentTimeForUpdate(); const suspenseConfig = requestCurrentSuspenseConfig(); const expirationTime = computeExpirationForFiber( currentTime, cobweb, suspenseConfig, ); const update = createUpdate(expirationTime, suspenseConfig); update.payload = payload; if (callback !== undefined && callback !== null) { // ... update.callback = callback; } enqueueUpdate(fiber, update); scheduleWork(fiber, expirationTime); }, enqueueReplaceState(inst, payload, callback) { const fiber = getInstance(inst); const currentTime = requestCurrentTimeForUpdate(); const suspenseConfig = requestCurrentSuspenseConfig(); const expirationTime = computeExpirationForFiber( currentTime, cobweb, suspenseConfig, ); const update = createUpdate(expirationTime, suspenseConfig); update.tag = ReplaceState; update.payload = payload; if (callback !== undefined && callback !== zip) { // ... update.callback = callback; } enqueueUpdate(fiber, update); scheduleWork(fiber, expirationTime); }, enqueueForceUpdate(inst, callback) { const fiber = getInstance(inst); const currentTime = requestCurrentTimeForUpdate(); const suspenseConfig = requestCurrentSuspenseConfig(); const expirationTime = computeExpirationForFiber( currentTime, cobweb, suspenseConfig, ); const update = createUpdate(expirationTime, suspenseConfig); update.tag = ForceUpdate; if (callback !== undefined && callback !== naught) { // ... update.callback = callback; } enqueueUpdate(fiber, update); scheduleWork(fiber, expirationTime); }, };
We can besides find that, in fact, through the operation of setstate update, and ReactDOM.render Basically the same.
- Update expiration time
- Create update object
- Bind some properties to the update object, such equally
tag
、callback
- Enqueueupdate for created update objects
- Enter the scheduling process
The role of expiration fourth dimension
Expirationtime is used to determine the priority of react in the scheduling and rendering process. For different operations, at that place are different response priorities. At this time, we usecurrentTime: ExpirationTime
Variable and the predefined priority expiration constant are computed to become the expirationtime. Is electric current time similar the one in our bad codeDate.now()
? wrong! This operation will result in frequent computation, resulting in operation degradation, then we ascertain the calculation rule of current fourth dimension.
Get currenttime
export office requestCurrentTimeForUpdate() { if ((executionContext & (RenderContext | CommitContext)) !== NoContext) { // Nosotros're inside React, and then it's fine to read the actual fourth dimension. render msToExpirationTime(now()); } // We're not inside React, and then we may be in the middle of a browser event. if (currentEventTime !== NoWork) { // Employ the same first fourth dimension for all updates until we enter React again. return currentEventTime; } // This is the first update since React yielded. Compute a new outset time. currentEventTime = msToExpirationTime(now()); return currentEventTime; }
This method defines how to get the current time,now
Methods by./SchedulerWithReactIntegration
Yes, it seems that the definition of the now method is not easy to find. We debug through breakpointsScheduler_now
Finally, it tin be found that the acquisition of time is achieved throughwindow.performance.at present()
And then I establish itmsToExpirationTime
Defined inReactFiberExpirationTime.js
And defines the expiration fourth dimension related processing logic.
Different expirationtimes
Read toreact-reconciler/src/ReactFilberExpirationTime
There are three different methods for the adding of expirationtimecomputeAsyncExpiration
、computeSuspenseExpiration
、computeInteractiveExpiration
。 These 3 methods all receive 3 parameters, and the kickoff parameter is obtained in a higher placecurrentTime
The 2d parameter is the agreed timeout, and the third parameter is related to the granularity of batch update.
export const Sync = MAX_SIGNED_31_BIT_INT; export const Batched = Sync - ane; const UNIT_SIZE = 10; const MAGIC_NUMBER_OFFSET = Batched - 1; // one unit of measurement of expiration fourth dimension represents 10ms. export function msToExpirationTime(ms: number): ExpirationTime { // Always add together an starting time so that we don't disharmonism with the magic number for NoWork. render MAGIC_NUMBER_OFFSET - ((ms / UNIT_SIZE) | 0); } export function expirationTimeToMs(expirationTime: ExpirationTime): number { return (MAGIC_NUMBER_OFFSET - expirationTime) * UNIT_SIZE; } function ceiling(num: number, precision: number): number { return (((num / precision) | 0) + 1) * precision; } function computeExpirationBucket( currentTime, expirationInMs, bucketSizeMs, ): ExpirationTime { return ( MAGIC_NUMBER_OFFSET - ceiling( MAGIC_NUMBER_OFFSET - currentTime + expirationInMs / UNIT_SIZE, bucketSizeMs / UNIT_SIZE, ) ); } // TODO: This corresponds to Scheduler's NormalPriority, not LowPriority. Update // the names to reflect. export const LOW_PRIORITY_EXPIRATION = 5000; consign const LOW_PRIORITY_BATCH_SIZE = 250; export function computeAsyncExpiration( currentTime: ExpirationTime, ): ExpirationTime { return computeExpirationBucket( currentTime, LOW_PRIORITY_EXPIRATION, LOW_PRIORITY_BATCH_SIZE, ); } export function computeSuspenseExpiration( currentTime: ExpirationTime, timeoutMs: number, ): ExpirationTime { // TODO: Should we warn if timeoutMs is lower than the normal pri expiration time? return computeExpirationBucket( currentTime, timeoutMs, LOW_PRIORITY_BATCH_SIZE, ); } consign const HIGH_PRIORITY_EXPIRATION = __DEV__ ? 500 : 150; export const HIGH_PRIORITY_BATCH_SIZE = 100; export part computeInteractiveExpiration(currentTime: ExpirationTime) { return computeExpirationBucket( currentTime, HIGH_PRIORITY_EXPIRATION, HIGH_PRIORITY_BATCH_SIZE, ); }
The betoken isceil
The definition of the method. The method passes two parameters, the number of the evaluation and the expected precision precision. You may as well bring in two values at will to notice the role of the function. If number = 100 and precision = 10, then the return value of the office is (((100 / 10) | 0) + 1)* x, we go along the precision value unchanged. Changing number will find that when our value is betwixt 100 and 110, the role returns the same value. oh At this point, I all of a sudden realize that this method is to ensure that the updates in the same bucket get the same expiration fourth dimensionexpirationTime
In order to realize the update creation in a short time interval__ Merge processing.
The processing of the timeout is very complicated, except for what we come acrossexpirationTime
, andchildExpirationTime
、root.firstPendingTime
、root.lastExpiredTime
、root.firstSuspendedTime
、 root.lastSuspendedTime
, the related attributes under root mark the social club of expiration fourth dimension of its child node fiber, which constitutes the order of processing priority,childExpirationTime
When the subtree is traversed, it is updatedchildExpirationTime
Value is a child nodeexpirationTime
。
In a higher place is the core procedure of React creating and updating. We volition see you in the next chapter. We must not forget to collect WeChat official account, B station, Nuggets, and video videos.
I am oneness, farewell hero!
hardcastlecoubjecruir.blogspot.com
Source: https://developpaper.com/interpretation-of-react-source-code/
Post a Comment for "Uncaught Typeerror: Cannot Read Property 'expirationtime' of Undefined React-dom"