Thousands of words of articles will help you understand what React is, what React has, and how to use React. (one)

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?

  1. Initialization phase
    constructor Constructor
    getDefaultProps props default value
    getInitialState state default value
  2. Mounting phase
    componentWillMount Called before component initialization and rendering
    render Component rendering
    componentDidMount Called after component is mounted to DOM< /span>
  3. 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
  4. 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 . componentDidUpdatecomponentWillUpdate

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 componentStacktrace 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 componentprops

  • 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 modifications console.log(), so ajaxdom

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:
  1. 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;
  2. If the child node changes, VirtualDOM will not calculate the change and re-render it twice;
  3. 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

  1. Maintainability is increased at the expense of some performance.
  2. Can make the framework cross-platform
  3. High level of abstraction of components

Disadvantages of Virtual Dom

  1. Rendering a large amount of DOM for the first time will be slightly slower due to the calculation of multiple layers of virtual DOM.
  2. Need to maintain a copy of the DOM in memory
  3. 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.

setStateMechanisms

setStateIs 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. statestatestate
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 setStateGet the updated value immediately, please get it in this callback function

  • setStatereceive a new status
  • The received new status will not be executed immediately, but will be stored inpendingStates (waiting queue)

setStateThe execution principle of

Can be divided into two categories:

  1. Batch update class: that is, the internal execution function of react and the execution logic of setState are batch update processing, including: react internal events (synthetic events) and life cycle;
  2. Non-batch update type: situations other than the above two situations, commonly seen: native events, setTimeout, fetch, etc.;< /span>

Two concepts:

  1. 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;
  2. 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, firstrenderThen executecallback,setStateThe 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 setStatesetStaterenderstatecallback

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

  1. setStateThe execution is divided into two major categories: one is life cycle and synthetic functions; the other is non-previous two situations;
  2. Both types, setState are executed synchronously, but in the batch update class, state and callback It is collected and processed lazily, which can be understood as asynchronous execution of data; instead of setState in the batch update class, it directly triggers update rendering.
  3. callback and state are collected at the same time, and processed uniformly after render.

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". onClickfiberprop

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.

  1. 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.
  2. 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:

  1. Tasks that need to be performed immediately
  2. Tasks that need to be performed during user inactivity
  3. normal tasks
  4. low priority tasks
  5. 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.

Guess you like

Origin blog.csdn.net/zw7518/article/details/124469084