Skip to content Skip to sidebar Skip to footer

Uncaught Typeerror: Cannot Read Property 'expirationtime' of Undefined React-dom

Interpretation of react source code

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.

ReactThe living life ofReactDOM.renderThis process will reserve a lot of necessities for its life. We volition follow this clue to explore baby likeReactAt 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.

Interpretation of react source code

First of allreact-dom/client/ReactDOMIn terms ofReactDOMIt 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./ReactDOMLegacyrenderThe 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.renderWhen theparentComponentIt 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,returnandcreateProtalThe 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,   ); }          

createLegacyRootDefined in./ReactDOMRootSpecifies 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 thecreateContainerTo create root, which creates theFiberRootThis 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 seeupdateContainerMethod, 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,computeExpirationForFiberMethod 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 createdcreateUpdateAnd 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/ReactBaseClassesAs 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.setStateWe are familiar with this API for a long time. For the update and cosmos of object components, definereact-reconciler/src/ReactFiberClassComponent.jsThe classcomponentupdater object defines theenqueueSetStateAndenqueueReplaceStateas well every bitenqueueForceUpdateObject method, observe the ii methods and find that the difference isenqueueReplaceStateandenqueueForceUpdateA tag is spring to the created update object. The blazon used to mark the update isReplaceStateneverthelessForceUpdateLet'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.

  1. Update expiration time
  2. Create update object
  3. Bind some properties to the update object, such equallytagcallback
  4. Enqueueupdate for created update objects
  5. 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: ExpirationTimeVariable 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,nowMethods by./SchedulerWithReactIntegrationYes, it seems that the definition of the now method is not easy to find. We debug through breakpointsScheduler_nowFinally, it tin be found that the acquisition of time is achieved throughwindow.performance.at present()And then I establish itmsToExpirationTimeDefined inReactFiberExpirationTime.jsAnd defines the expiration fourth dimension related processing logic.

Different expirationtimes

Read toreact-reconciler/src/ReactFilberExpirationTimeThere are three different methods for the adding of expirationtimecomputeAsyncExpirationcomputeSuspenseExpirationcomputeInteractiveExpiration。 These 3 methods all receive 3 parameters, and the kickoff parameter is obtained in a higher placecurrentTimeThe 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 isceilThe 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 dimensionexpirationTimeIn 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, andchildExpirationTimeroot.firstPendingTimeroot.lastExpiredTimeroot.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,childExpirationTimeWhen the subtree is traversed, it is updatedchildExpirationTimeValue 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"