life cycle
What is life cycle
In one sentence: the process from creation to destruction is the life cycle
So what are the stages of the react life cycle?
- Initialization phase
constructor
Constructor
getDefaultProps
props default value
getInitialState
state default value - Mounting phase
componentWillMount
Called before component initialization and rendering
render
Component rendering
componentDidMount
Called after component is mounted to DOM< /span> - Update phase
componentWillReceiveProps
Called before the component will receive new props
shouldComponentUpdate
Whether the component needs to be updated
componentWillUpdate
Called before the component is updated< /span> Called after component update
render
Component rendering
componentDidUpdate
- Unloading phase
componentWillUnmount
The new life cycle of React16 has deprecated the three methods componentWillMount
, componentWillReceiveProps
, componentWillUpdate
, and added getDerivedStateFromProps
, getSnapshotBeforeUpdate
to replace the three deprecated hook functions;
These three hooks have not been deleted in React16. But it cannot be mixed with the new hook functions. React17 will delete these three hook functions and add new error handling (componentDidCatch
)
So how to use the new method?
getDerivedStateFromProps
: Each time the component is rerendered, including after the component is built (after the virtual dom, before the actual dom is mounted), after each time new props or state are obtained; it will be returned each time after receiving new props. An object serves as the new state. Returning null means that the state does not need to be updated; with componentDidUpdate
, it can cover all usages of componentWillReceiveProps
.
getSnapshotBeforeUpdate
: Trigger time: when update occurs, after render and before component DOM rendering; return a value as the third parameter of componentDidUpdate
; cooperate with < a i=2>, can cover all usages of . componentDidUpdate
componentWillUpdate
componentDidCatch
: If some error occurs during any lifecycle method or rendering phase of any child component, then the componentDidCatch
() method is called. This method is used to implement error boundaries for React applications. It is called during the commit phase, so unlike getDerivedStateFromError
() which is called during the render phase, this method allows the use of side-effects
. This method is also used to log errors. It receives two parameters, error
and info
; error
: This is an error raised by descendant components. info
: It stores the componentStack
trace of which component caused this error.
side effect
-
First explain
纯函数(Pure function)
: Giving a function the same parameters will always return the same value, and there are no side effects; when this concept is applied to React, it means giving a function< a i=2> the same, always renders the same view, and has no other side effects; the advantage of pure components is that it is easy to monitor data changes, easy to test, improve rendering performance, etc.; a>Pure component
props
-
Side effects (
Side Effect
) refer to a function doing things that have nothing to do with the return value of its own operation, such as: modifying global variables, modifying passed parameters, or even are considered side effects; operations and modificationsconsole.log()
, soajax
dom
Virtual Dom
Definition of Virtual Dom
It is essentially a JS object, which is a more lightweight description of the DOM.
React puts forward a new idea to solve the pain point of operating DOM, that is, always refresh the page as a whole. When the before and after state changes occur, React will automatically update the UI, but the disadvantage is that it is very slow. Therefore, the unchanged DOM nodes are left unchanged, and only the changed DOM nodes are created and replaced to achieve node reuse, so the problem is transformed into how to compare the differences between the two DOM nodes. Because DOM is a tree deconstruction, the complexity of the completed tree structure diff algorithm is O(n^3).
React has made three optimizations to reduce complexity:
- If the parent nodes are different, abandon the comparison of child nodes, directly delete the old node and add a new node to re-render;
- If the child node changes, VirtualDOM will not calculate the change and re-render it twice;
- Compare nodes by setting unique key values; the real DOM has a lot of attributes, most of which are of no use to DIff, so if you use more lightweight JS objects to replace complex DOM nodes, you can Avoid a large number of query operations on the DOM.
The role of Virtual Dom
- Maintainability is increased at the expense of some performance.
- Can make the framework cross-platform
- High level of abstraction of components
Disadvantages of Virtual Dom
- Rendering a large amount of DOM for the first time will be slightly slower due to the calculation of multiple layers of virtual DOM.
- Need to maintain a copy of the DOM in memory
- This is appropriate if the virtual DOM changes heavily. But for single, frequent updates, the virtual DOM will spend more time processing calculations. So, if you have a DOM node with relatively few pages, it's actually possible to be slower with a virtual DOM.
setState
Mechanisms
setState
Is it synchronous or asynchronous?
In React's life cycle and synthetic events, React is still in its update mechanism. No matter how many times it is calledsetState
, the update will not be performed immediately, but will be The updated value is stored in _pendingStateQueue
, and the component to be updated is stored in dirtyComponent
.
When the last update mechanism is completed, taking the life cycle as an example, all components, that is, the top-level component didmount
will set the batch flag to false. At this time, the components in dirtyComponent
and the state in _pendingStateQueue
will be taken out and updated. This ensures that the component is not re-rendered multiple times.
componentDidMount() {
this.setState({
index: this.state.index + 1
})
console.log('state', this.state.index);
}
So, like the above code, when we get immediately after executing setState
, we cannot get the updated version a>, because it is in the batch processing mechanism of React, is temporarily stored, and will be updated uniformly after the batch processing mechanism is completed. So. itself is not asynchronous, but React’s batch processing mechanism gives the illusion of asynchronousness. state
state
state
setState
In asynchronous code and native events:
componentDidMount() {
setTimeout(() => {
console.log('调用setState');
this.setState({
index: this.state.index + 1
})
console.log('state', this.state.index);
}, 0);
}
Such as the above code, when we callsetState
in asynchronous code, according to the asynchronous mechanism of JavaScript, the asynchronous code will be temporarily stored first, and will be processed after all synchronous codes are executed. Execute. At this time, React's batch processing mechanism has been completed, and the processing flag is set to false
. At this time, call setState
again to execute the update immediately and get Updated results.
Calling setState
in a native event will not trigger React’s batch processing mechanism, so you can get the latest results immediately.
Best Practice
setState
The second parameter of receives a function that will be called after React's batching mechanism is completed, so you want to call setState
Get the updated value immediately, please get it in this callback function
setState
receive a new status- The received new status will not be executed immediately, but will be stored in
pendingStates
(waiting queue)
setState
The execution principle of
Can be divided into two categories:
- Batch update class: that is, the internal execution function of
react
and the execution logic ofsetState
are batch update processing, including: react internal events (synthetic events) and life cycle; - Non-batch update type: situations other than the above two situations, commonly seen: native events,
setTimeout
,fetch
, etc.;< /span>
Two concepts:
- Transaction: It can be understood that a normal function is wrapped in another layer. This layer of package processing includes one or more processing functions before the execution of the function (initialize function), and one or more processing functions after the execution of the function (close function); many logical processing in React use the concept of transactions;
- The relationship and difference between synthetic events and native events:
Difference: Native events are events written in the addEventListener way! Synthetic events are to directly write onClick, onChange, etc. in react;
Relationship: Synthetic events can be understood as react’s wrapping of native events; native events It is equivalent to the normal function in the transaction concept above, and the transaction formed after packaging processing is the synthetic event in react.
In the native event,setState
will directly trigger the render
update, so the execution order of the example in the native event is, firstrender
Then executecallback
,setState
The transaction is executed, and then printing is executed. What is printed is the status after the update of setState
, and so on, so the printing order of the above native events appears, which is very clear.
This is not the case for synthetic events. It directly initiates transaction 1 and starts updating the status in batches before the function is executed (isBatchedUpdates
is true
, and the default value is < /span>. and Update, instead does two things: collect will not be triggered at this time. in the synthesis event. At this time, it is in the batch update state, and false
!), after turning it on, execute setState
setState
render
state
callback
Batch update is turned off by default, then it will be executed directlybatchedUpdates
(this function is the update rendering function). Here is the fork of whether batch update status is enabled: when batch update is enabled, the status push
is added to the array (dirtyComponents
).
After collecting the status, what does the close
function that executes the transaction do? One is to close the batch update status, and the other is to formally initiate the processing of the collected status. Here, a new transaction is opened: transaction 2. Transaction 2, after complex processing, updates the collected state, that is, dirtyComponents
. After processing, the close
function of transaction 2 is executed, which resets the entire updated state, which is also collected here in transaction 1. callback
;; a>
瀻结setState
:
setState
The execution is divided into two major categories: one is life cycle and synthetic functions; the other is non-previous two situations;- Both types,
setState
are executed synchronously, but in the batch update class,state
andcallback
It is collected and processed lazily, which can be understood as asynchronous execution of data; instead ofsetState
in the batch update class, it directly triggers update rendering. callback
andstate
are collected at the same time, and processed uniformly afterrender
.
Synthetic event mechanism and principles
Due to the characteristics of the fiber
mechanism, when a fiber node is generated, its corresponding dom
node may not be mounted yet, < An event handling function such as a i=3> is used as the of the node, so it cannot be directly bound to the real DOM node. To this end, React provides an event mechanism of "Top-level registration, event collection, unified triggering". onClick
fiber
prop
The so-called "Top-level registration" actually binds a unified event processing to the root
element function. "Event collection" refers to when an event is triggered (actually the event processing function on root
is executed), Construct a synthetic event object, and follow the bubbling or capturing path to collect the real event handling functions in the component. "Unified triggering" occurs after the collection process, and the collected events are executed one by one and share the same synthetic event object. An important point here is that the event listener bound to root
is not the event processing function we wrote in the component. Pay attention to this difference, which will be mentioned below.
The above is a brief description of the React event mechanism. This mechanism avoids the problem of being unable to bind events directly to DOM nodes and can make good use offiber
the hierarchy of the tree. relationship to generate event execution paths, thereby simulating event capture and bubbling, and also brings two very important features:
Categorizing events can include different priorities on the tasks generated by the events
Provide synthetic event objects to smooth out browser compatibility differences
Next, the event mechanism will be explained in detail, throughout the life cycle of an event from registration to execution.
- The event processing function is not bound to the element of the component, but to the root. This is related to the structural characteristics of the fiber tree, that is, the event processing function can only be used as a prop of the fiber.
- The event listener bound to the root is not the event handler function we wrote in the component, but a listener that holds the event priority and can pass the event execution stage flag.
Synthetic event object
The event object obtained in the event handling function in the component is not a native event object, but an object synthesized by ReactSyntheticEvent
. It resolves compatibility differences between different browsers. Abstract it into a unified event object to relieve developers of their mental burden.
Fiber
A large number of simultaneous calculation tasks block the browser's UI rendering. By default, JS operations, page layout and page drawing are all; they run in the main thread of the browser, and they are mutually exclusive. If JS operations continue to occupy the main thread, the page will not be updated in time. When we call setState
to update the page, React will traverse all the nodes of the application, calculate the differences, and then update the UI. The whole process is done in one go and cannot be interrupted. If there are many page elements, the entire process may take more than 16 milliseconds, and frame drops may easily occur.
The basic idea to solve the problem of the main thread being occupied by JS operations for a long time is to cut the operation into multiple steps and complete them in batches. That is to say, after completing a part of the task, control is returned to the browser, allowing the browser time to render the page. Wait until the browser is finished, then continue the unfinished task.
window.requestIdleCallback()
Functions are called sequentially when the browser is idle, allowing developers to perform background or low-priority tasks in the main event loop without affecting delayed but critical events such as animations and user interactions. Functions are generally executed in first-in, first-out order, unless the function's timeout expires before the browser calls it.
The internal operations of the React framework can be divided into 3 layers:
- Virtual DOM layer, describing what the page looks like.
- The Reconciler layer is responsible for calling component life cycle methods, performing Diff operations, etc.
- The Renderer layer renders corresponding pages according to different platforms. The more common ones are ReactDOM and ReactNative.
The biggest change in versions after react16 is undoubtedly the Reconciler layer. The React team also gave it a new name, called Fiber Reconciler.
The execution process of Fiber Reconciler will be divided into 2 stages.
- In the first stage, a Fiber tree is generated and the node information that needs to be updated is obtained. This step is a gradual process and can be interrupted.
- In the second stage, the nodes that need to be updated are updated in batches at once, and this process cannot be interrupted.
The interruptible feature of phase one allows tasks with higher priority to be executed first, which greatly reduces the probability of page frame dropping from the framework level.
When Fiber Reconciler performs Diff calculation in stage one, it will generate a Fiber tree. This tree is generated by adding additional information based on the Virtual DOM tree. It is essentially a linked list.
The Fiber tree will be generated in one go when rendering for the first time. When Diff is needed later, a new tree will be generated based on the existing tree and the latest Virtual DOM information. Every time a new node is generated in this new tree, control will be returned to the main thread to check whether there are higher priority tasks that need to be executed. If not, continue the process of building the tree.
If there are higher-priority tasks that need to be performed during the process, Fiber Reconciler will discard the tree being generated and execute it again when it is idle.
During the process of constructing the Fiber tree, Fiber Reconciler will save the node information that needs to be updated in the Effect List. When phase 2 is executed, the corresponding nodes will be updated in batches.
How is Fiber implemented?
链表、一次Fiber循环所有节点访问两次、requestIdleCallback
Deep understanding of Fiber
need
1. 每一个状态的改变不是都需要马上反应在UI界面上
2. 不同的状态改变应该有不同的优先级,如动画,输入等应该有更高的优先级
3. 对于大量状态的改变复杂操作应该进行更好的调度,避免UI页面卡顿
Fiber structure
The overall structure of the fiber tree is a two-way circular linked list. This structure can find the corresponding node more quickly.
In order to know the information of the previous node during the Reconcile process, the new fiber node needs to be associated with the old fiber node.
There will be two fiber trees in Fiber at the same time. The process of each Reconcile is the process of building a new fiber tree. After commit, the new fiber tree becomes the current fiber tree, and so on. .
Fiber Effect
During the Reconcile process, the node needs to be set to a state that needs to be compared to the old node. After each fiber node is constructed (set its own effectTag status), if there is an effect, it will put itself and its descendant elements into the effects of the parent node. In this way, layer by layer, all the effects will be stored in the new fiber tree. The fiber node to be processed. Then enter the commit stage, convert all fiber nodes to dom, and refresh the UI page.
Fiber Scheduling
Since Fiber is a virtual stack, it needs to be scheduled. We can use this function to execute our code when the browser is idle, so as not to block page rendering.
Fiber priority
For a better user experience, tasks with higher priority need to be executed first, such as animation, input, etc. There are five priorities in Fiber, and each priority corresponds to an expiration time.
Time slicing, in layman’s terms, means dividing tasks into several types, specifically:
- Tasks that need to be performed immediately
- Tasks that need to be performed during user inactivity
- normal tasks
- low priority tasks
- Tasks performed when the browser is idle
Execute according to priority. If a new task is inserted, it will also be reordered according to priority
This module is implemented using two new es6 APIs, namely a>window.requestAnimationFrame
and window.requestIdleCallback
. The specific usage can be foundMDN
. In each cycle, if there are expired tasks, then the expired tasks must be executed no matter what, and then if there is remaining time, the tasks with the smaller expiration time will be executed first, and so on.