Although function components are now used, class components still have some advantages that function components cannot replace, such as some unique life cycles, the convenience of storing variables without requiring a lot of useRef, and the convenience of instance method calls.
The React version is 17.0.1.
Class component Fiber node creation
The Fiber node the components of a parent node after entering reconcileChildren method through createFiberFromTypeAndProps method to create, In this method through the prototype. IsReactComponent to judge whether the node for ClassComponent.
export function createFiberFromTypeAndProps(
type: any, // React$ElementType
key: null | string,
pendingProps: any,
owner: null | Fiber,
mode: TypeOfMode,
lanes: Lanes,
) :Fiber {
// omit irrelevant code...
let fiberTag = IndeterminateComponent;
if (typeof type === 'function') {
/ / by prototype. IsReactComponent distinguish the type of component
if (shouldConstruct(type)) {
// Mark it as a class componentfiberTag = ClassComponent; }}// omit irrelevant code...
return fiber;
}
/ / by prototype. IsReactComponent distinguish the type of component
function shouldConstruct(Component: Function) {
const prototype = Component.prototype;
return!!!!! (prototype && prototype.isReactComponent); }Copy the code
Due to the need to inherit the Component class components, all existing prototype. IsReactComponent, the node is marked as class components, follow-up will enter class components.
Class component instance creation and update
The Fiber node is marked as a ClassComponent in the previous step, and when the node enters the beginWork phase it enters the updateClassComponent method by judgment.
/ /... Omit irrelevant code
case ClassComponent: {
// Class component type is the class itself, not an instance of the class
const Component = workInProgress.type;
const unresolvedProps = workInProgress.pendingProps;
/ / defaultProps merger
const resolvedProps =
workInProgress.elementType === Component
? unresolvedProps
: resolveDefaultProps(Component, unresolvedProps);
return updateClassComponent(
current,
workInProgress,
Component,
resolvedProps,
renderLanes,
);
}
/ /... Omit irrelevant code
Copy the code
Whenever a class component is first mounted or updated, it goes to updateClassComponent.
function updateClassComponent(
current: Fiber | null,
workInProgress: Fiber,
Component: any,
nextProps: any,
renderLanes: Lanes,
) {
// omit irrelevant code...
/ / class instance
const instance = workInProgress.stateNode;
let shouldUpdate;
// mount
if (instance === null) {
// omit irrelevant code...
// Create and initialize the class instance
constructClassInstance(workInProgress, Component, nextProps);
mountClassInstance(workInProgress, Component, nextProps, renderLanes);
shouldUpdate = true;
} else if (current === null) {
// Continue rendering after interrupt...
} else {
// update
shouldUpdate = updateClassInstance(
current,
workInProgress,
Component,
nextProps,
renderLanes,
);
}
// Return to the subfiber node
const nextUnitOfWork = finishClassComponent(
current,
workInProgress,
Component,
shouldUpdate,
hasContext,
renderLanes,
);
return nextUnitOfWork;
}
Copy the code
Mount and Update are judged separately in the updateClassComponent.
When the Mount
Mount creates an instance, assigns an updater(i.e., setState, forceUpdate, etc.), and initializes updateQueue. The main methods called are constructClassInstance and mountClassInstance.
constructClassInstance
The constructClassInstance method creates an instance of the class and binds it to the Fiber node, assigning the updater.
function constructClassInstance(workInProgress: Fiber, ctor: any, props: any,) :any {
let isLegacyContextConsumer = false;
let unmaskedContext = emptyContextObject;
let context = emptyContextObject;
// omit context-related code...
// Create an instance
const instance = new ctor(props, context);
// Assign state to memoizedState of the Fiber node
conststate = (workInProgress.memoizedState = instance.state ! = =null&& instance.state ! = =undefined
? instance.state
: null);
/ / assignment updater
adoptClassInstance(workInProgress, instance);
// omit irrelevant code...
return instance;
}
function adoptClassInstance(workInProgress: Fiber, instance: any) :void {
/ / assignment updater
instance.updater = classComponentUpdater;
workInProgress.stateNode = instance;
// Access the fiber node through the instance._reactInternals property
setInstance(instance, workInProgress);
}
Copy the code
mountClassInstance
The mountClassInstance method assigns props and state to the class instance, initializes updateQueue, and executes the getDerivedStateFromProps lifecycle to obtain the new state. Also execute the componentWillMount life cycle as judged.
The subsequent value of state is updated by performing update in updateQueue.
function mountClassInstance(workInProgress: Fiber, ctor: any, newProps: any, renderLanes: Lanes,) :void {
/ / class instance
const instance = workInProgress.stateNode;
/ / assignment props, the state
instance.props = newProps;
instance.state = workInProgress.memoizedState;
instance.refs = emptyRefsObject;
// Initialize UpdateQueue
initializeUpdateQueue(workInProgress);
const contextType = ctor.contextType;
if (typeof contextType === 'object'&& contextType ! = =null) {
// Attach the context to the instance context
instance.context = readContext(contextType);
}
// execute updateQueue to calculate the new state
processUpdateQueue(workInProgress, newProps, instance, renderLanes);
instance.state = workInProgress.memoizedState;
const getDerivedStateFromProps = ctor.getDerivedStateFromProps;
// Execute getDerivedStateFromProps to assign to state
if (typeof getDerivedStateFromProps === 'function') {
applyDerivedStateFromProps(
workInProgress,
ctor,
getDerivedStateFromProps,
newProps,
);
instance.state = workInProgress.memoizedState;
}
/ / call componentWillMount
if (
typeofctor.getDerivedStateFromProps ! = ='function' &&
typeofinstance.getSnapshotBeforeUpdate ! = ='function' &&
(typeof instance.UNSAFE_componentWillMount === 'function' ||
typeof instance.componentWillMount === 'function')) {/ / call UNSAFE_componentWillMount
callComponentWillMount(workInProgress, instance);
// Execute updateQueue to handle the update initiated by UNSAFE_componentWillMount
processUpdateQueue(workInProgress, newProps, instance, renderLanes);
// Assign a new state
instance.state = workInProgress.memoizedState;
}
// Flags increment Update with componentDidMount
if (typeof instance.componentDidMount === 'function') { workInProgress.flags |= Update; }}Copy the code
When the Update
Update calls updateClassInstance to handle updates.
updateClassInstance
function updateClassInstance(current: Fiber, workInProgress: Fiber, ctor: any, newProps: any, renderLanes: Lanes,) :boolean {
/ / class instance
const instance = workInProgress.stateNode;
// Clone the current update ue to workInProgress
cloneUpdateQueue(current, workInProgress);
// When Fiber completes the beginWork phase, memoizedProps is assigned to pendingProps
const unresolvedOldProps = workInProgress.memoizedProps;
const oldProps =
workInProgress.type === workInProgress.elementType
? unresolvedOldProps
: resolveDefaultProps(workInProgress.type, unresolvedOldProps);
instance.props = oldProps;
const unresolvedNewProps = workInProgress.pendingProps;
// context
const oldContext = instance.context;
const contextType = ctor.contextType;
let nextContext = emptyContextObject;
if (typeof contextType === 'object'&& contextType ! = =null) {
nextContext = readContext(contextType);
} // ...
const getDerivedStateFromProps = ctor.getDerivedStateFromProps;
// Whether a new life cycle is used
const hasNewLifecycles =
typeof getDerivedStateFromProps === 'function' ||
typeof instance.getSnapshotBeforeUpdate === 'function';
/ / call UNSAFE_componentWillReceiveProps
if (
!hasNewLifecycles &&
(typeof instance.UNSAFE_componentWillReceiveProps === 'function' ||
typeof instance.componentWillReceiveProps === 'function')) {if( unresolvedOldProps ! == unresolvedNewProps || oldContext ! == nextContext ) { callComponentWillReceiveProps( workInProgress, instance, newProps, nextContext, ); }}// Reset the forceUpdate identifier before executing updateQueue
resetHasForceUpdateBeforeProcessing();
const oldState = workInProgress.memoizedState;
let newState = (instance.state = oldState);
// Execute updateQueue to obtain the new state
processUpdateQueue(workInProgress, newProps, instance, renderLanes);
newState = workInProgress.memoizedState;
// Do not understand this paragraph
if( unresolvedOldProps === unresolvedNewProps && oldState === newState && ! hasContextChanged() && ! checkHasForceUpdateAfterProcessing() ) {if (typeof instance.componentDidUpdate === 'function') {
if( unresolvedOldProps ! == current.memoizedProps || oldState ! == current.memoizedState ) { workInProgress.flags |= Update; }}if (typeof instance.getSnapshotBeforeUpdate === 'function') {
if( unresolvedOldProps ! == current.memoizedProps || oldState ! == current.memoizedState ) { workInProgress.flags |= Snapshot; }}return false;
}
/ / getDerivedStateFromProps execution
if (typeof getDerivedStateFromProps === 'function') {
applyDerivedStateFromProps(
workInProgress,
ctor,
getDerivedStateFromProps,
newProps,
);
newState = workInProgress.memoizedState;
}
// Use the forceUpdate flag and shouldComponentUpdate to determine whether an update is needed
const shouldUpdate =
checkHasForceUpdateAfterProcessing() ||
checkShouldComponentUpdate(
workInProgress,
ctor,
oldProps,
newProps,
oldState,
newState,
nextContext,
);
// Update required
if (shouldUpdate) {
// Call the UNSAFE_componentWillUpdate life cycle
if (
!hasNewLifecycles &&
(typeof instance.UNSAFE_componentWillUpdate === 'function' ||
typeof instance.componentWillUpdate === 'function')) {if (typeof instance.componentWillUpdate === 'function') {
instance.componentWillUpdate(newProps, newState, nextContext);
}
if (typeof instance.UNSAFE_componentWillUpdate === 'function') { instance.UNSAFE_componentWillUpdate(newProps, newState, nextContext); }}if (typeof instance.componentDidUpdate === 'function') {
workInProgress.flags |= Update;
}
if (typeof instance.getSnapshotBeforeUpdate === 'function') { workInProgress.flags |= Snapshot; }}else {
// Do not understand this paragraph
if (typeof instance.componentDidUpdate === 'function') {
if( unresolvedOldProps ! == current.memoizedProps || oldState ! == current.memoizedState ) { workInProgress.flags |= Update; }}if (typeof instance.getSnapshotBeforeUpdate === 'function') {
if( unresolvedOldProps ! == current.memoizedProps || oldState ! == current.memoizedState ) { workInProgress.flags |= Snapshot; } } workInProgress.memoizedProps = newProps; workInProgress.memoizedState = newState; }// Update the props,state,context of the instance
instance.props = newProps;
instance.state = newState;
instance.context = nextContext;
return shouldUpdate;
}
Copy the code
finishClassComponent
Both Mount and Update require the finishClassComponent method, which returns the Child node after the reconcileChildren is processed.
function finishClassComponent(
current: Fiber | null,
workInProgress: Fiber,
Component: any,
shouldUpdate: boolean,
hasContext: boolean,
renderLanes: Lanes,
) {
// The tag needs to be assigned ref
markRef(current, workInProgress);
constdidCaptureError = (workInProgress.flags & DidCapture) ! == NoFlags;// No update required
if(! shouldUpdate && ! didCaptureError) {return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);
}
const instance = workInProgress.stateNode;
let nextChildren;
// There was an error and getDerivedStateFromError was not declared
if (
didCaptureError &&
typeofComponent.getDerivedStateFromError ! = ='function'
) {
// Leave children unrendered and leave it to componentDidCatch
nextChildren = null;
} else {
// Execute render to get children
nextChildren = instance.render();
}
if(current ! = =null && didCaptureError) {
forceUnmountCurrentAndReconcile(
current,
workInProgress,
nextChildren,
renderLanes,
);
} else {
/ / deal with children
reconcileChildren(current, workInProgress, nextChildren, renderLanes);
}
workInProgress.memoizedState = instance.state;
return workInProgress.child;
}
Copy the code
Class component update scheduling
Class updates exist in the updateQueue on the Fiber node, which stores Update information. Class components can create updates using setState and add them to the updateQueue to initiate Update scheduling. The processUpdateQueue method is called to calculate the new state when the updateClassInstance method is executed during Update.
Structure of Update Ue and Update
When the mountClassInstance method is executed while the class component is mounted, the initializeUpdateQueue method is internally called to initialize the updateQueue.
export function initializeUpdateQueue<State> (fiber: Fiber) :void {
const queue: UpdateQueue<State> = {
baseState: fiber.memoizedState, // Update calculates the new state based on baseState
firstBaseUpdate: null.// Priority dependent, skipped update
lastBaseUpdate: null.// Priority dependent, skipped update
shared: {
pending: null.// The current update list
},
effects: null.// Update callback, corresponding to setState second parameter
};
fiber.updateQueue = queue; / / initialization
}
Copy the code
The createUpdate method is called by executing setState to create the update and add it to updateQueue. Update is a circular list, and the next field points to the next update.
export function createUpdate(eventTime: number, lane: Lane) :Update< * >{
const update: Update<*> = {
eventTime,
lane, // Priority is related
tag: UpdateState, // Update the state value according to the tag judgment
payload: null.// corresponds to the first argument of setState
callback: null.// corresponds to the second argument of setState
next: null.// Because it is a linked list, it points to the next update
};
return update;
}
Copy the code
processUpdateQueue
The processUpdateQueue method is called when the class component is updated to get the new state.
/ / updateQueue execution
export function processUpdateQueue<State> (workInProgress: Fiber, props: any, instance: any, renderLanes: Lanes,) :void {
// Never null in ClassComponent
const queue: UpdateQueue<State> = (workInProgress.updateQueue: any);
// The global identifier determines whether the update was initiated by forceUpdate
hasForceUpdate = false;
// Update list skipped because priority was last updated
let firstBaseUpdate = queue.firstBaseUpdate;
let lastBaseUpdate = queue.lastBaseUpdate;
// If there are pending updates, splice them to baseUpdate
let pendingQueue = queue.shared.pending;
if(pendingQueue ! = =null) {
queue.shared.pending = null;
// Disconnect the last one from the first one so that the pendingQueue is not a loop
const lastPendingUpdate = pendingQueue;
const firstPendingUpdate = lastPendingUpdate.next;
lastPendingUpdate.next = null;
// Connect pending updates to the Base Queue
if (lastBaseUpdate === null) {
firstBaseUpdate = firstPendingUpdate;
} else {
lastBaseUpdate.next = firstPendingUpdate;
}
lastBaseUpdate = lastPendingUpdate;
// Ensure that current and workInProgress are consistent
const current = workInProgress.alternate;
if(current ! = =null) {
// omit code...}}if(firstBaseUpdate ! = =null) {
let newState = queue.baseState;
let newLanes = NoLanes;
let newBaseState = null;
let newFirstBaseUpdate = null;
let newLastBaseUpdate = null;
let update = firstBaseUpdate;
do {
const updateLane = update.lane;
const updateEventTime = update.eventTime;
// Tasks with insufficient priority
if(! isSubsetOfLanes(renderLanes, updateLane)) {// clone skipped Update
const clone: Update<State> = {
eventTime: updateEventTime,
lane: updateLane,
tag: update.tag,
payload: update.payload,
callback: update.callback,
next: null};// Connect to firstBaseUpdate or lastBaseUpdate
if (newLastBaseUpdate === null) {
newFirstBaseUpdate = newLastBaseUpdate = clone;
// The state value of the skipped Update will be used next time
newBaseState = newState;
} else {
newLastBaseUpdate = newLastBaseUpdate.next = clone;
}
newLanes = mergeLanes(newLanes, updateLane);
} else {
// The priority of the Update cannot be skipped
// If a previous update was skipped, add laseBaseUpdate to ensure continuity for the next update
if(newLastBaseUpdate ! = =null) {
const clone: Update<State> = {
eventTime: updateEventTime,
// NoLane will not be skipped the next time it is executed
lane: NoLane,
tag: update.tag,
payload: update.payload,
callback: update.callback,
next: null}; newLastBaseUpdate = newLastBaseUpdate.next = clone; }// Calculate the new state according to update
newState = getStateFromUpdate(
workInProgress,
queue,
update,
newState,
props,
instance,
);
const callback = update.callback;
// The callback function pushes into the Effects array
if(callback ! = =null) {
workInProgress.flags |= Callback;
const effects = queue.effects;
if (effects === null) {
queue.effects = [update];
} else{ effects.push(update); }}}// Next update
update = update.next;
if (update === null) {
pendingQueue = queue.shared.pending;
if (pendingQueue === null) {
break;
} else {
// call setState again in the setState function to enter the judgment
const lastPendingUpdate = pendingQueue;
const firstPendingUpdate = ((lastPendingUpdate.next: any): Update<State>);
lastPendingUpdate.next = null;
update = firstPendingUpdate;
queue.lastBaseUpdate = lastPendingUpdate;
queue.shared.pending = null; }}}while (true);
if (newLastBaseUpdate === null) {
newBaseState = newState;
}
queue.baseState = ((newBaseState: any): State);
queue.firstBaseUpdate = newFirstBaseUpdate;
queue.lastBaseUpdate = newLastBaseUpdate;
markSkippedUpdateLanes(newLanes);
workInProgress.lanes = newLanes;
workInProgress.memoizedState = newState; // reflect the state value of the page}}Copy the code
The processUpdateQueue method performs updateQueue to calculate the new state value, mainly because it contains the priority and skipped Update. The main logic is to iterate through the Update list to get the new state.
The state value is obtained using the getStateFromUpdate method.
getStateFromUpdate
State is handled within the getStateFromUpdate function based on the Update type, focusing on the UpdateState type initiated by setState.
function getStateFromUpdate<State> (workInProgress: Fiber, queue: UpdateQueue
, update: Update
, prevState: State, nextProps: any, instance: any,
) :any {
switch (update.tag) {
// omit code...
/ / tag for UpdateState
case UpdateState: {
const payload = update.payload;
let partialState;
if (typeof payload === 'function') {
// When the first argument is a function
partialState = payload.call(instance, prevState, nextProps);
} else {
// The first argument is object
partialState = payload;
}
if (partialState === null || partialState === undefined) {
return prevState;
}
/ / state
return Object.assign({}, prevState, partialState); },/ / tag for ForceUpdate
case ForceUpdate: {
hasForceUpdate = true;
returnprevState; }}return prevState;
}
Copy the code
SetState and forceUpdate
The setState and forceUpdate methods are methods that inherit from the Component prototype chain and are essentially called at Mount when this.updater is assigned.
Component.prototype.setState = function(partialState, callback) {
this.updater.enqueueSetState(this, partialState, callback, 'setState');
};
Component.prototype.forceUpdate = function(callback) {
this.updater.enqueueForceUpdate(this, callback, 'forceUpdate');
};
Copy the code
This. Updater is assigned to constructClassInstance when adoptClassInstance is called in the constructClassInstance method at Mount time.
// adoptClassInstance...
instance.updater = classComponentUpdater;
// Access the fiber node through the instance._reactInternals property
setInstance(instance, workInProgress);
Copy the code
classComponentUpdater
Updater essentially calls the classComponentUpdater method.
const classComponentUpdater = {
enqueueSetState(inst, payload, callback) {
// Fetch the fiber node from the _reactInternals property of the instance
const fiber = getInstance(inst);
const eventTime = requestEventTime();
const lane = requestUpdateLane(fiber);
/ / create the update
const update = createUpdate(eventTime, lane);
update.payload = payload;
if(callback ! = =undefined&& callback ! = =null) {
update.callback = callback;
}
/ / Update the team
enqueueUpdate(fiber, update);
// Initiate update scheduling
scheduleUpdateOnFiber(fiber, lane, eventTime);
},
enqueueForceUpdate(inst, callback) {
const fiber = getInstance(inst);
const eventTime = requestEventTime();
const lane = requestUpdateLane(fiber);
const update = createUpdate(eventTime, lane);
update.tag = ForceUpdate;
if(callback ! = =undefined&& callback ! = =null) { update.callback = callback; } enqueueUpdate(fiber, update); scheduleUpdateOnFiber(fiber, lane, eventTime); }};Copy the code
The main difference between setState and forceUpdate is that the tag type of Update is different. The getStateFromUpdate method returns different results when updateQueue obtains the state from Update.
Their callbacks are executed during subsequent COMMIT phases.
Class component lifecycle execution
The following life cycle does not include the UNSAFE life cycle, which is not recommended for future use, and some extraneous code is omitted.
Render phase
With concurrent mode enabled in the future, the current UNSAFE lifecycle may be executed multiple times due to render interrupts or high priorities, and while this is not an issue for now, it should be avoided.
constructor
Constructor actually passes context as a second argument when executing, which is not present on the document.
function constructClassInstance(
// ...
) :any {
// Create an instance
const instance = new ctor(props, context);
}
Copy the code
shouldComponentUpdate
ShouldComponentUpdate is called every time in the updateClassInstance method during Update.
function updateClassInstance(
// ...
) :boolean {
const shouldUpdate =
checkHasForceUpdateAfterProcessing() ||
/ / call shouldComponentUpdate
checkShouldComponentUpdate(
workInProgress,
ctor,
oldProps,
newProps,
oldState,
newState,
nextContext,
);
}
Copy the code
getDerivedStateFromProps
GetDerivedStateFromProps will trigger this method before each render, as documented, and it will be called at Mount and Update to get a new state value by executing the function, which will be merged to the current state, It also maintains the base Estate value for updateQueue in some cases.
// ...
const getDerivedStateFromProps = ctor.getDerivedStateFromProps;
if (typeof getDerivedStateFromProps === 'function') {
applyDerivedStateFromProps(
workInProgress,
ctor,
getDerivedStateFromProps,
newProps,
);
/ / assigned to
instance.state = workInProgress.memoizedState;
}
Copy the code
componentDidMount
Although componentDidMount is not executed during render, it is flagged during Render and only executed during commit.
function mountClassInstance(
// ...
) :void {
// Flags increment Update with componentDidMount
if (typeof instance.componentDidMount === 'function') { workInProgress.flags |= Update; }}Copy the code
ComponentDidMount and getSnapshotBeforeUpdate
As with componentDidMount, flags is required for render, but it checks whether props and state are changed.
function updateClassInstance(
// ...
) :boolean {
if (typeof instance.componentDidUpdate === 'function') {
if( unresolvedOldProps ! == current.memoizedProps || oldState ! == current.memoizedState ) { workInProgress.flags |= Update; }}if (typeof instance.getSnapshotBeforeUpdate === 'function') {
if (
unresolvedOldProps !== current.memoizedProps ||
oldState !== current.memoizedState
) {
workInProgress.flags |= Snapshot;
}
}
}
Copy the code
The commit phase
The COMMIT phase is divided into three phases
- BeforeMutation phase
- Mutation stages
- Layout stage
BeforeMutation phase
BeforeMutation phase before DOM manipulation.
getSnapshotBeforeUpdate
Check whether current is Update and execute the getSnapshotBeforeUpdate method. As described in the document, this life cycle can be used as the scrollbar position because the DOM value is still old.
function commitBeforeMutationLifeCycles(
current: Fiber | null,
finishedWork: Fiber,
) :void {
switch (finishedWork.tag) {
// ...
case ClassComponent: {
// 判断flags有Snapshot,在render阶段会打上flags
if (finishedWork.flags & Snapshot) {
// Check whether the current is Mount or Update using current
if(current ! = =null) {
const prevProps = current.memoizedProps;
const prevState = current.memoizedState;
const instance = finishedWork.stateNode;
const snapshot = instance.getSnapshotBeforeUpdate(
finishedWork.elementType === finishedWork.type
? prevProps
: resolveDefaultProps(finishedWork.type, prevProps),
prevState,
);
// The return value is stored in an internal variableinstance.__reactInternalSnapshotBeforeUpdate = snapshot; }}return;
}
// ...}}Copy the code
Mutation stages
The Mution phase is manipulating the DOM.
componentWillUnMount
When Fiber node contains flags Deletion, finally get into commitUnmount method, by calling componentWillUnMount safelyCallComponentWillUnmount method.
function commitUnmount(finishedRoot: FiberRoot, current: Fiber, renderPriorityLevel: ReactPriorityLevel,) :void {
switch (current.tag) {
// ...
case ClassComponent: {
safelyDetachRef(current);
const instance = current.stateNode;
if (typeof instance.componentWillUnmount === 'function') {
safelyCallComponentWillUnmount(current, instance);
}
return;
}
// ...}}Copy the code
Layout stage
The Layou phase is after DOM manipulation.
ComponentDidMount and componentDidMount
ComponentDidMount and componentDidMount are executed in the same function. Current === null determines which function to execute.
function commitLifeCycles(
finishedRoot: FiberRoot,
current: Fiber | null,
finishedWork: Fiber,
committedLanes: Lanes,
) :void {
switch (finishedWork.tag) {
case ClassComponent: {
const instance = finishedWork.stateNode;
if (finishedWork.flags & Update) {
/ / the mount
if (current === null) {
/ / componentDidMount execution
instance.componentDidMount();
} else {
// Update the props and state from the current Fiber node
const prevProps =
finishedWork.elementType === finishedWork.type
? current.memoizedProps
: resolveDefaultProps(finishedWork.type, current.memoizedProps);
constprevState = current.memoizedState; instance.componentDidUpdate( prevProps, prevState, instance.__reactInternalSnapshotBeforeUpdate, ); }}// Effects are performed on updateQueue, where setState and forceUpdate callback are stored
const updateQueue: UpdateQueue<
*,
> | null = (finishedWork.updateQueue: any);
if(updateQueue ! = =null) {
commitUpdateQueue(finishedWork, updateQueue, instance);
}
return; }}}Copy the code
conclusion
More than simple simple analyses the type of Fiber components from source node to create, component class instance creation, update, update the scheduling, the implementation of life cycle, contrast Hooks back, I think some kind of components is quite convenient, though most functions components can be implemented, but still take some time to realize the corresponding function with Hooks.
Today looked at the source code class article written by others, I can not help but feel that I write is probably to see their own, the basic calculation of a note.