preface

When learning a grammar or framework, there are always some key concepts or perceptions to keep in mind. These concepts may seem simple in a few words, but they often imply good design ideas and practices; Lack of awareness does not hinder normal development, but it requires many detours to meet difficult problems or improve development efficiency. As a developer with pursuit, how can you stay on the surface? So what are the concepts we need to know about React? Today, let’s take a look at it. Note: This document knowledge is based on React17;

First, come into view

Start by openingReact Chinese official document:



You can see that the key words that jump out at you are:

JavaScript libraries for building user interfaces,** Declarative **,** Componentization **,Learn once, write anywhere.

Nouns are no longer new, but they are no less important.

JavaScript libraries for building user interfaces

1. Understand concepts

This one is simple and easy to understand:

  • Making it easier for developers to quickly and easily build user interfaces – the real meaning of introducing a front-end framework;
  • React is a library of functions written in JavaScript syntax that can be imported into a project and used directly without additional conversion or compilation.

Official Documentation blog: “Why did we build React?” It started as an internal FaceBook project and was launched in May 2013.

React version number management

React version management is also interesting:

If you look at the history of the codebase, you’ll see that it’s been stable and efficient in production since May 2013 when React was launched. But for a long time, the React team has been able to React with (0.3.0, 0.4.0,… , 0.14.0) Only upgrade the second version in the update iteration; Hasn’t released the V1.0 version that developers were expecting.



The first release v0.3.0:

It wasn’t until April 2016 that it officially moved to the main semver release to maintain stability guarantees; Instead of the V1 version, it jumped from V0.14.8 to V15.0.0. One of the reasons for this is that the React team wanted to say:Although the previous releases were minor releases, they are guaranteed to be as stable as the main release.



React Main version atlas:





The release that will have the biggest impact on our development: the V16.8.0 release in February 2019React HookA stable version has been released.

Three, a study, anywhere to write

This mainly includes the following points:

  1. React hosting part of the UI can be introduced at any time without refactoring the existing project architecture.
  2. React syntax supports multi-terminal development;

1. Without refactoring existing project code, you can introduce React to build part OF UI at any time

React is a gradual framework, it was designed to be adopted gradually from the beginning, and we can use React selectively as needed. Its core library focuses only on the view layer, making it easy to integrate with third-party libraries or existing projects.

  1. To use React optionally, you simply need to connect an HTML node to the React component and bind it. “Portal”
  2. We can also build complex applications from scratch that are taken over entirely by React with the help of common toolchains and supporting libraries. To get the best development experience; “Portal”

2. React syntax supports multi-terminal development

React syntax can be used not only for web pages, but also for server rendering in conjunction with Node, or for Native mobile applications using React Native.

2.1 How does React support multi-terminal syntactic unification?

The answer to this question is to understand the relationship between React and the React-DOM library. React internally divides its libraries into syntax API libraries and rendering libraries to implement core functions.

  1. The React library is just an Api wrapper that defines React syntax. It doesn’t know how these features are implemented;
  2. Most of the implementation is in the “renderer.” Such asreact-dom,react-dom/server,react-nativeThese are common renderers;

    Renderer packages expose platform-specific apis and implementations;

This separation of API definitions and implementation details allows us to focus on the React feature experience, regardless of platform differences. Developers can even customize platform-specific renderers to support more platforms. This is why both React and react-dom need to be updated when we want to use new features in the React syntax.

To explore further,

2.2 such assetStateWhen the API is defined in the React package, what is the way to trigger the renderer to render the UI?

The React-DOM renderer “injects” implementations of functions such as setState into the generic React package, essentially using dependency injection to make components more declarative. When the code runs, the renderer sets a special object (updater) on the contained component. The internal implementation of setState calls methods on this Updater object in response to the renderer, allowing the React DOM to schedule and process updates. React library setState definition:

// React library part source
Component.prototype.setState = function(partialState, callback) {
  // ...
  // Call the enqueueSetState method on the injected Updater object in response to the renderer
  this.updater.enqueueSetState(this, partialState, callback, 'setState');
};
Copy the code

React-dom source code for setState:

// React Dom simplifies the code
let inst; // The current context
let queue = []; // Store the queue temporarily
const updater = {
  ...
  // Implementation of enqueueSetState on the updater object:
  enqueueSetState: function(publicInstance, currentPartialState) {
    if (queue === null) {
      warnNoop(publicInstance, 'setState');
      return null; } queue.push(currentPartialState); }}; .// isClass Is a class component
// if (isClass) {
// inst = new Component(element.props, publicContext, updater);
// }. inst.updater = updater; .Copy the code

Hooks use a “dispatcher” object instead of the updater field. When you call react.usestate (), react.useeffect (), or any of the other built-in hooks, these calls are forwarded to the current Dispatcher.

Four, declarative

React makes it easy to create interactive UIs. Designed with neat views for each state of your application, React effectively updates and renders components correctly when data changes. Writing your UI declaratively makes your code more reliable and easier to debug.

Many of you have heard the term declarative programming all over the place. So what exactly is declarative programming?

Imperative programming

Speaking of declarative programming, imperative programming has to be mentioned first. Imperative programming describes how to do this, and the developer writes all the process code step by step. Examples of common noodle code, process control code. Is generally the first way to think of writing code – step by step to write a program needs to perform the steps;

Declarative programming

  • Declarative programming is about what you do, not how you do it.
  • It does not show the description and control steps, but by assembling a pre-declared, encapsulated logical units to constitute the whole goal;
  • Declarative based on the underlying good encapsulation; At run time, it is actually processed as assignment, order, condition and other process-oriented processing.
  • Encapsulation and abstraction can be reused, greatly simplifying programmer work and collaborative development.

According to the framework syntax to encapsulate the logical unit, the programming process of declaring and assembling components is declarative programming. For example: SQL, various top-level frameworks; The biggest characteristic is that I only state what I want, without saying exactly how I’m going to do it.

Functional programming

Declarativeness is an important feature of functional programming,

  • Functional programming is a paradigm of declarative programming, but it is not limited to declarative programming. It also has some other characteristics: higher-order functions, etc.
  • Functions in functional programming are first class citizens, which means that functions are data that you can save, retrieve, and pass around in your application like variables.
    • Functions are equal to other data types and can be assigned to other variables, passed as arguments to another function, or returned as a value from another function.

Before Act 16.8, the pure function components and high order components used in React were the embodiment of functional programming. React16.8+ introduces React Hooks to fully embrace functional programming;

4. How to understand React’s declarative UI programming?

In the wild days before React, Vue and other declarative UI frameworks were introduced, when a page was developed, various data and interactive operations were coupled to each other, which was not easy to maintain. With the help of Jquery, EJS and other page templates, although functional division has been achieved, but it still does not solve the difficulties in maintenance, data rendering trouble, complicated interaction and other problems; A declarative UI framework, on the other hand, can do:

  • The code is concise, the project code structure is clear; Can practice high cohesion, low coupling;
  • Reliable, the corresponding data state corresponds to the rendering result; Interactive and predictable rendering;
  • Abstract, not directly manipulating the DOM;
  • Convenient debugging, and facilitate continuous maintenance iteration;

V. Componentization

Everything in React is components, and components are first-class citizens. Various design patterns are properly applied, modules are split, and efficient and easy to maintain code is developed. Good at componentization development, is a required ability to use the React framework.

1. Benefits of componentization

  • Componentization is a concrete manifestation of declarative UI programming. It contains the benefits of declarative UI programming mentioned above: high cohesion, low coupling, simplicity, clarity, reliability, etc., which I won’t go into here.

  • In addition, the abstraction of components reinforces the boundaries of responsibility;

    • Bring reusability and improve development efficiency. With the help of community open source UI component libraries such as ANTD, it greatly reduces the business development threshold; In addition, business components based on project precipitation can also greatly improve the efficiency of subsequent business iterative development.
    • Brings certainty and reduces maintenance costs. Especially for complex or older projects, maintainability is an important indicator. Small changes or problem fixes can be located along deterministic links between components to minimize impact points.

2. Component splitting guidelines

  1. Partition components by data boundary;
  • Define the functions and responsibilities of props and state;
  • The number of props should not be too large, and the necessary data flow between components should be specified.
  • The minimum principle is to extract state from the upper component as far as possible to avoid unnecessary derived state;
  • .
  1. Split the components by visual function, and split them in turn:
  • Base class component
  • Business common class components
  • Complex business is divided according to the page block, and data flow between block components is done well;

More complex UIs are formed by breaking them down into self-contained, status-specific pieces based on the page area structure or function points. Of course, the design principle is a guiding principle, often in the actual complex project needs to consider more dimensions, can not be generalized. Componentized separation and assembly is a process that needs practice and exploration to make it better and better. Excellent componentized development also reveals the artistic aesthetics of design. We need to be nurtured through continuous optimization of real projects, exploration and reading about good open source projects.

6. Component Design Patterns – High Order Component (HOC)

Be clear: higher-order components and higher-order functions are essentially the same thing. We implement a function, pass in a component, then implement a function inside the function to extend the incoming component, and finally return a new component. This is the concept of a higher-order component, which is designed to reuse code better.

Component communication – One-way data flow

React implements data state flow through one-way data flow.

1. Father-son communication

  • The parent component uses props to pass data to the child component.
  • The child component cannot modify the props directly. Instead, it must notify the parent component to change the data by calling the parent function.

This kind of father-son communication is a typical one-way data flow.

2. Communication between sibling components

This situation can be resolved by ascending the data state to a common parent component, where state and event functions are maintained. Let’s say one of the siblings changes the state in the parent by calling the event function passed by the parent, and then the parent passes the state to the other sibling.

3. Communication across multi-layer components

After version 16.3, we can use the Context API to solve the problem of communicating across multi-level components.

Context provides a method to pass data across the component tree without having to manually add props for each layer of components. “Portal”

4. Any component

Communication between any component can be handled by global state management such as Redux, Mobx, Dva, or Event Bus. Of course, you can solve all of the above data communication situations with just a global state manager such as Redux. However, I don’t recommend it, because it only adds complexity to the project, and the global state manager should only be used for the maintenance of global state.

Data driven

I think data-driven is the core concept that needs to be kept in mind and put into action in the actual development of React. In the team development process, I often encountered children’s implementation is not in place, such as: monitoring scrolling, setting animation and other interactions, direct operation of the real DOM; Or distrust the data-driven rendering results and flow process, and forcibly intervene; The React interface is completely data-driven: You don’t need to manipulate the DOM directly, but instead use React’s ability to drive DOM rendering and interactions through data state; Subsequent page changes, such as direct operation of the data state can be synchronized changes. In addition, React will only make necessary updates through the Virtual DOM technology mentioned below to achieve the purpose of rendering optimization.

Nine, Virtual DOM

1. What is a Virtual DOM?

The Virtual DOM is a programming concept. In this concept, the UI is kept in memory in an idealized, or “virtual,” representation that is synchronized with the “real” DOM through libraries such as ReactDOM. This process is called coordination. – the React website

Based on Virtual DOM technology, the class library implemented by JavaScript (on the basis of DOM operation to establish an abstraction layer, using JavaScript objects to replace DOM nodes, bearing the interaction with the real DOM), to help developers avoid direct real and tedious DOM operation and UI rendering. At the same time, it is also an abstract programming mode, derived from the declarative UI programming, DOM Diff algorithm, React Fiber engine, etc., are part of the “Virtual DOM” concrete embodiment;

2. Virtual DOM Advantages?

  • Using the Virtual DOM as a compatibility layer enables us to interconnect with non-Web systems to achieve cross-end development.
  • Similarly, we can render on other platforms through Virtual DOM, such as SSR, isomorphic rendering and so on.
  • Opens the door to functional UI programming, with a high degree of abstraction of components.
  • Hide the details of DOM operation, with the framework to improve project maintainability;
  • In the application scenarios where DOM operations are frequent and data is frequently updated in a small amount, this feature provides excellent performance advantages.

3. Is the Virtual DOM faster than the native DOM?

For this point, you can refer to the “great insights” a few years ago.

This view is very one-sided. The Virtual DOM will eventually parse into the native DOM and perform native DOM operations. The Virtual DOM has an advantage only when the data is changed. If the page is displayed for the first time and does not have to be changed, it has no advantage. Don’t be fooled into thinking that Virtual DOM is just fast, Diff isn’t free, and ultimately native API call rendering. The real value is not just performance, but also the advantages:

  1. With framework encapsulation, maintainability is improved, not performance optimization is prioritized. The framework gives you assurance that you can still give you decent performance without having to manually optimize.
  2. Compared to DOM operations, JS computations are extremely cheap.

4. How does React’s DOM Diff algorithm work?

React creates a virtual DOM tree after the React component is first rendered. React builds a new virtual DOM tree when the component’s props or state is updated. React needs to determine what’s really changing based on the differences between the two trees and effectively update the UI to keep the current UI in sync with the latest tree. This involves the pros and cons of Diff algorithm. Traditional Diff algorithm: the nodes are compared sequentially through cyclic recursion, the algorithm complexity reaches O(n), and the efficiency is very low.

React’s Diff algorithm

React diff algorithm: it is the process of converting Virtual DOM tree into actual DOM tree with minimal operation. React converts O(N3) complexity to O(n) complexity using three strategies:

1. Tree Diff Compares two Virtual DOM trees at the same level. If the comparison finds that the corresponding node does not match or does not exist, the node and its children are completely deleted and no further comparison is performed. In this way, you can complete the comparison of the whole DOM tree by traversing it once. In this way, Diff algorithm simply considers node position transformation of the same level. If it is across levels, there are only operations of creating new nodes and deleting old nodes.

A hierarchical comparison of two components of the same type will produce a similar tree structure; Having two components of different types is determined to be dirty, so replacing all nodes of the entire component generates a different tree structure.

When nodes are at the same level, there are three types of node Diff: delete, insert, and move. Insert: For new nodes, insert directly; Delete: For nodes that cannot be reused and are actually removed, the old ones are deleted and new ones are created. Move: For the same group of child nodes to be differentiated by adding a unique key, the position can be moved.

5. What’s the difference between React and Vue’s Diff process

  • Vue tracks the dependencies of each component during the rendering process, so there is no need to re-render the entire component tree.
  • React All child components trigger execution and rerendering whenever the state of the top component of the application is changed (this can be controlled via the shouldComponentUpdate lifecycle method or other means such as React.memo).
  • React Diff is Dom, Vue Diff is data;

6. Why does any top-level update in React only trigger coordination instead of locally updating the affected components?

The design is intentional. Interaction time is a key metric for Web applications, and traversing the model to set up fine-grained listeners wastes precious time. In addition, interactions in many applications tend to result in updates that are either small (button hovers) or large (page transformations), so fine-grained subscriptions only waste memory resources.

Ten, the React of Fiber

React has introduced an entirely new infrastructure in version 16.0 -Fiber. As a new coordination engine after the refactoring of the core algorithm, its main purpose is to enable incremental rendering of the Virtual DOM: the ability to divide the rendering work into blocks and distribute it across multiple frames.

1. Why introduce Fiber

In fact, it is to solve the original synchronous rendering, and can not interrupt the problem. Prior to React16, synchronous rendering caused performance problems when rendering a large, deep React component tree structure. Specifically, in the synchronized rendering mode, if the data change of the uppermost component triggers the rendering, the subcomponent will be synchronized to trigger the rendering, and then the subcomponent will be synchronized to render…… Finally, the whole component tree is rendered. The call stack will be very long, and there will be a lot of complex update logic in the process, so the diFF calculation process may cause the main thread to be blocked for a long time. While JS running environment is single-threaded, long-term occupation will cause the browser rendering engine can not timely perform UI rendering (more than 16ms), and there will be the performance problem of frame dropping. In addition, users’ interactive operations and page animations will not respond, which will affect user experience. Fiber is designed to solve this problem. The solution to the fiber-reinforced mechanism is that Fiber slices this time-consuming synchronous render task into multiple task blocks. After completing each task, give other tasks on the main thread a chance to execute. This way the main thread is not blocked by Virtual DOM computation and rendering exclusively. This process is also known as coordination, and the Fiber scheduler is free to schedule these small chunks according to priority. To achieve the purpose of incrementally updating the render in segments without affecting the experience. React has its own computational logic for how to prioritize, and it’s worth exploring. For example, for things with high real-time performance like animation, React will pause the update every 16 ms to ensure animation execution first, and then continue the rendering schedule, so as to ensure that the animation does not get stuck.

2. The Fiber task has two execution phases: “Render phase” and “Commit phase” :

  1. Reconcile(render) – Reconciling:

The render phase is where Fiber is coordinated. It belongs to the Virtual DOM operation stage. In the scheduling DIff algorithm, the new and old Virtual DOM are compared to find out the content to be updated, and the update tree is generated. Fiber Reconciler scheduling designs this process as a simple JS computation process, which can be cached, interrupted, and resumed.

  1. Commit – Commit an update:

The commit phase is when you actually work on the host tree. It belongs to the interface drawing stage. After the content to be updated is obtained in the previous step, the update is submitted, and the corresponding renderer (such as React-DOM) is called for UI drawing. This process is synchronous and cannot be interrupted until the current execution of the component is complete. The reason is to prevent in the rendering process, eliminate the so-called intermediate state, resulting in page structure jitter, affect the user experience.

What is the effect of introducing Fiber on the life cycle function?

After React16.4, the execution of component declaration cycle functions is divided into two phases: Render and Commit. The former process can be suspended, suspended, or restarted; The latter cannot be stopped and will keep updating the interface until it is finished.

Render phase:

  • componentWillMount
  • componentWillReceiveProps
  • shouldComponentUpdate
  • componentWillUpdate

The Commit phase

  • componentDidMount
  • componentDidUpdate
  • componentWillUnmount

Because the Render phase can be interrupted, lifecycle functions performed by the Render phase can be called multiple times, causing bugs. Therefore, several functions called in the Render phase should be avoided except shouldComponentUpdate, and a new API has been introduced in V16.4 to address this issue: GetDerivedStateFromProps used to replace componentWillReceiveProps, this function can be in initialization and is invoked when the update. GetSnapshotBeforeUpdate is used to replace componentWillUpdate, which is called after the DOM update and before the DOM update to read the latest DOM data. In my own just learn React for a period of time, like many developers have a mistake: the Vue life cycle rules hardcopy apply, always want to task to the first life cycle function to mention, do AJAX requests in componentWillMount.

3. So why not do AJAX in componentWillMount?

A component’s componentWillMount is called less than a few microseconds earlier than its componentDidMount.

  1. From the above rendering process, we know that the Render phase componentWillMount may be interrupted midway, after the interrupt rendering again to do again, will appear the interface request call N times. In contrast, if you put AJAX on componentDidMount, because componentDidMount is in the second stage, you won’t repeat the call many times.
  2. In addition, in the server side isomorphic rendering mode, if the data is obtained in componentWillMount, the fetch data will be executed twice, once on the server and once on the client. Not in componentDidMount.

We now know that the right thing to do is to place the code according to the semantics of each function, not as far ahead as possible.

11. What is the event mechanism of React? Synthetic events/native events

React’s synthesized events are different from the browser’s native events and do not map directly to native events.

1. What does it mean?

React events are not bound to the actual DOM after they are registered. Instead, all events are bound to the Document by means of an event proxy. This approach not only reduces memory consumption, but also allows for uniform subscription and removal of events when a component mounts and is destroyed. In addition, the events that bubble onto the Document are not native browser events, but synthetic events implemented by React itself. It is a cross-browser wrapper for browser native events. It also has the same interface as the browser’s native events, including stopPropagation() and preventDefault(), which prevent event passing.

2. What is the purpose of React to synthesize events?

  1. Gives React the ability to develop across browsers; Synthetic event is a cross-browser native event wrapper that smoothes out interoperability issues between browsers;
  2. Reduced memory consumption and the ability to uniformly subscribe and remove events when a component mounts and is destroyed;

For native browser events, the browser creates an event object for each listener. If you have a lot of event listeners, then you need to allocate a lot of event objects, resulting in a high memory allocation problem.

For synthetic events, however, there is a pool of events to manage their creation and destruction. When the event needs to be used, the objects are reused from the pool. After the event callback, the properties on the event object are destroyed so that the event object can be reused next time. The latest React 17, however, removed the event pool.

After the language

The preface should be supplemented by the epilogue

The better you understand the concept, the smoother it will be.

Individual every time to learn the official website, every time to read the source code, there are new understanding and harvest. What I am doing now is summarizing what I have seen and learned in the React practice process during continuous learning.

This article does not cover the important React Hooks, which will be discussed in the next one.