The React based

JSX

const element = <h1>Hello, world! </h1>;Copy the code

JSX, which is neither a string nor HTML, is essentially a JavaScript syntax extension, and much closer to JavaScript, is an object created via React.createElement(), called the React element.

React doesn’t force JSX, but it separates concerns by putting tags and logic together to form components. At the same time, JSX protects against XSS injection attacks.

Render elements

  1. React elements are immutable objects. Once created, you cannot change its child elements or attributes. The only way to update the UI is to create an entirely new element and pass it to reactdom.render ().

  2. React only updates what it needs to update. The React DOM compares an element and its children to their previous state and only updates are necessary to bring the DOM to its intended state.

Components & Props

  • Function component: Takes a unique “props” object with data and returns a React element. This type of component is called a “function component” because it is essentially a JavaScript function.
  • Class component: looks like
function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}
Copy the code
class Welcome extends React.Component { render() { return <h1>Hello, {this.props.name}</h1>; }}Copy the code
  • Props read-only: All React components must protect their Props as if they were pure functions.
  • State allows the React component to dynamically change its output based on user actions, network responses, or other changes.

A component must never modify its props, whether using a function declaration or through a class declaration. Such a function is called a “pure function” because it does not attempt to change the incoming parameters, and the same incoming parameters always return the same result under multiple calls.

State& Life cycle

setState(updater,[callback])
Copy the code

In React, if the event handler is raised by React (such as onClick), the setState call will not update this.state synchronously.

Why asynchronous? If the setState updates state synchronously, and the update of state triggers a rerendering of the component, then each setState will render the component, which is a significant performance drain.

  1. Normal React bound events: asynchronous updates
  2. Events bound through addEventListener: synchronous updates
  3. Handle click events with setTimeoutt: synchronous update

Use the compoentDidUpdate or setState callback function to ensure that it is triggered after the application is updated. Batch updates are implemented based on a queue and a variable lock, isBatchingUpdates.

Use the State pose correctly:

  1. Do not modify State directly

  2. Calls to setState are not immediately updated

  3. All components use the same update mechanism, when all components didmount, the parent didmount, and then perform the update

  4. The updates of each component are merged, and each component triggers only one update lifecycle.

  5. In hook functions and synthesis events:

React is still in its update mechanism with isBranchUpdate set to true in the React lifecycle and compositing events.

In this case, no matter how many times setState is called, the update is not performed. Instead, the updated state is stored in _pendingStateQueue and the updated component is stored in the dirtyComponent.

When the last update mechanism has been executed, for example in the life cycle, all components, the topmost component didmount, will set isBranchUpdate to false. The previously accumulated setstates are executed.

  1. Asynchronous functions and native events

If react is in an update process when the setState is called, the current update will be temporarily stored until after the last update has been executed. This process gives the illusion of asynchrony.

In the life cycle, according to the JS asynchronous mechanism, the asynchronous function will be temporarily stored and executed after all synchronous code is executed. At this time, the last update process has been executed.

When isBranchUpdate is set to false, you can call setState to immediately execute the update and get the result.

  1. ComponentDidMount calls setstate

It will trigger an extra render, but it will happen before the browser flushers the screen. This ensures that even though render() will be called twice in this case, the user will not see the intermediate state.

ComponentDidMount itself is in an update, and if we call setState again, we will render again in the future, causing unnecessary performance waste, which can be fixed by setting the initial value in most cases.

  1. Failure to call setState for componentWillUpdate and componentDidUpdate causes an infinite loop and crashes the program.

  2. Recommendation: Use the function to pass the state value when calling setState, and get the latest updated state in the callback function.

Life cycle:

  1. When component instances are created and inserted into the DOM, their lifecycle calls are called in the following order:
constructor()
static getDerivedStateFromProps()
render()
componentDidMount()
Copy the code

Note: The following lifecycle methods are becoming obsolete and should be avoided in new code: UNSAFE_componentWillMount()

  1. Update An update is triggered when the props or state of a component changes. The lifecycle of component updates is called in the following order:
static getDerivedStateFromProps()
shouldComponentUpdate()
render()
getSnapshotBeforeUpdate()
componentDidUpdate()
Copy the code

Note: The following methods are becoming obsolete and should be avoided in new code:

UNSAFE_componentWillUpdate() UNSAFE_componentWillReceiveProps()

  1. Uninstall calls the following methods when a component is removed from the DOM:
componentWillUnmount()
Copy the code

The event processing

  1. In React you cannot prevent the default behavior by returning false. Must explicitly callpreventDefault.

React implements a set of event mechanism by itself, simulates the process of event bubble and capture, adopts event proxy, batch update and other methods, and eliminates the compatibility problems of various browsers.

  1. The order in which React events are executed versus native events
  • Everything that happened at ReactIt's mounted in document
  • React events are not processed until the actual DOM is emitted and bubbles into the Document
  • So the native event is executed first
  • Then execute the React synthesis event
  • Finally, execute the event that is actually mounted on the Document
  1. Can REACT events and native events be mixed?

It is best not to mix react events and native events.

If stopPropagation is executed in a native event, it will invalidate other React events. Because the events for all the elements will not bubble onto the Document.

This binding: You must be careful with this in JSX callbacks. In JavaScript, class methods are not bound to this by default.

There are three ways:

  1. In the constructor, bind the following:this.handleClick = this.handleClick.bind(this);
  2. When a class defines an event handler as a method, use the arrow function:handleClick = () => {console.log('this is:', this); }
  3. Use the arrow function directly in the callback function:<button onClick={() => this.handleClick()}>Click me</button>

Note:

Creates a different callback function each time a Button is rendered. In most cases, this is fine, but if the callback function is passed to child components as a prop, those components may undergo additional re-rendering. We usually recommend binding in the constructor or using the Class Fields syntax to avoid this type of performance problem.

Composition vs Inheritance

React has a very powerful combination pattern. We recommend using composition rather than inheritance for code reuse across components. Props and combinations give you the flexibility to clearly and safely customize the look and behavior of your components. Note: Components can accept any props, including basic data types, React elements, and functions.

  1. Use a special{props.children}To pass their child components into the render result
  2. In rare cases, you may need to leave a few “holes” in a component. In this case, instead of using children, we can use our own convention: pass the required content into the props and use the corresponding prop, similar to the slotslotThe concept of.

Context

Context provides a way to share such values between components without having to explicitly pass props through the component tree.

Context is designed to share data that is “global” to a component tree, such as the currently authenticated user, subject, or preferred language.

The main application scenario of Context is that many components at different levels need to access the same data. Use with caution, as this makes the component less reusable. If you just want to avoid passing properties through layers, component composition is sometimes a better solution than context.

One solution without a context is to pass the child component itself, so the intermediate component doesn’t need to know what props the child component uses.

Error boundary

JavaScript errors in part of the UI shouldn’t crash the entire app. To address this, React 16 introduces a new concept called error boundaries.

<ErrorBoundary>
  <MyWidget />
</ErrorBoundary>
Copy the code

The Error boundary is a React component that catches and prints JavaScript errors that occur anywhere in its child component tree, and it renders the alternate UI instead of the collapsed child component tree.

Error boundaries catch errors during rendering, in lifecycle methods, and in constructors throughout the component tree.

[Code optimization point] Error bounds do not capture errors that occur in the following scenarios:

  • Event handling (learn more)
  • Asynchronous code (such as setTimeout or requestAnimationFrame callbacks)
  • Server-side rendering
  • Errors thrown by itself (not by its child components)

Refs forward

Ref forwarding is a technique for automatically passing a Ref through a component to a child component. This technique is especially useful for higher-order components, also known as HOC. Ref forward is an optional feature that allows some component to receive a Ref and pass it down (in other words, “forward” it) to a child component.

Fragments

A common pattern in React is for a component to return multiple elements. Fragments allow you to group sublists without adding additional nodes to the DOM.

render() {
  return (
    <React.Fragment>
      <ChildA />
      <ChildB />
      <ChildC />
    </React.Fragment>
  );
}
Copy the code

Or use the phrase: <>

High order component

Definition: A higher-order component is a function that takes a component as an argument and returns a value for a new component. HOC does not modify an incoming component, nor does it use inheritance to copy its behavior. Instead, HOC forms new components by wrapping them in container components. HOC is a pure function with no side effects.

High Order Component (HOC) is an advanced technique used in React to reuse component logic. Instead of being part of the React API, HOC is a design pattern based on the React combinatorial features.

const EnhancedComponent = higherOrderComponent(WrappedComponent);
Copy the code

A component converts props to a UI, and a high-level component converts a component to another component. For example, connect for Redux

Note:

  1. Do not use HOC in the Render method. Each call to render creates a new EnhancedComponent, causing the subtree to be unmounted and remounted every time!
  2. Be sure to copy static methods. You can automatically copy all non-react static methods using hoist-non-react-statics
  3. Refs will not be passed.

Collaborate with third-party libraries

We’re going to add a ref to this root DOM element. In componentDidMount, we can get a reference to it so we can pass it to the jQuery plug-in.

To prevent React from touching the DOM after it is mounted, we will return an empty

from render(). this

The element has neither attributes nor child elements, so React has no reason to update it so that the jQuery plug-in can manage this part of the DOM freely

class SomePlugin extends React.Component { componentDidMount() { this.$el = $(this.el); this.$el.somePlugin(); } componentWillUnmount() { this.$el.somePlugin('destroy'); } render() { return <div ref={el => this.el = el} />; }}Copy the code

Performance optimization

  1. Deploy with the production version and remove some warnings
  2. Virtualization long list.” Virtual scrolling technology. This technique renders only a limited amount of content in a limited amount of time and miraculously reduces the time spent rerendering components and the number of DOM nodes created.react-windowreact-virtualizedIs a popular virtual scroll library.
  3. Avoid mediation. You can go throughOverride the lifecycle method shouldComponentUpdate for speed. This method will be triggered before re-rendering. The default implementation always returns true. If you know when your component does not need to be updated, you can skip the entire rendering process by returning false in shouldComponentUpdate.

Inherit react.pureComponent instead of writing shouldComponentUpdate(). It overrides the shouldComponentUpdate() implementation with the current shallow comparison to the previous props and state.

shouldComponentUpdate(nextProps, nextState) {
  return true;
}
Copy the code
  1. The power of immutable data. Instead of changing the original object, use… The extension operator or object.assign returns a new Object.

The Diff algorithm

  1. When comparing two trees, React first compares the root nodes of both trees.
  • React removes the original tree and creates a new one when the root node is a different type of element. componentWillUnmount() -> componentWillMount() -> componentDidMount()

  • When comparing two React elements of the same type, React retains the DOM node and only compares and updates the changed attributes. And then the child nodes recurse.

  1. Child node recursion

When adding an element at the end of the child element list, the update cost is relatively small. If you simply insert the new element into the table header, the update overhead will be high, and you will not realize that you should keep the remaining ones, but instead rebuild each child element. This can cause performance problems. This is solved by adding a key.

Try to use the same node types and stable, predictable keys.

Render Prop

Render Prop is a function prop that tells a component what to render. Use Props instead of render.

It is important to remember that a render prop is called a render prop because of the mode, and you do not have to use the mode with a prop called render.

Be careful when using the Render Props with the React.pureComponent. If you create functions in the Render method, then using Render Prop negates the benefit of using React.pureComponent. Because a shallow comparison of props always returns false, and in this case each render will generate a new value for the render prop.

The usage of Key

React decides whether to destroy or update a component based on the key:

  • If the key is the same and the component changes, React will only update the component properties that changed.
  • If the key is different, the component will destroy the previous component and render the entire component again.

There are some problems with using index as key:

When the order of the element data source changes, it is rerendered. If you use a unique ID as a key, the values and keys of the child components are not changed, but the order is changed, so React just moves them, not rerenders them.

Virtual DOM

About whether performance can be improved

Many articles say that VitrualDom can improve performance, but this is actually quite one-sided.

Direct manipulation of the DOM is performance intensive, no doubt about it. However, with VitrualDom React can’t avoid manipulating the DOM.

If it’s the first rendering, VitrualDom doesn’t have any advantages, even though it does more computation and consumes more memory.

The advantage of VitrualDom lies in React’s Diff algorithm and batch processing strategy. React calculates how to update and render the DOM before the page is updated. In fact, we can judge and implement this calculation process by ourselves when we directly operate DOM, but it will definitely consume a lot of energy and time, and what we do by ourselves is often not as good as React. So, React helped us “boost performance” in the process.

So, I’m more likely to say that VitrualDom helps us improve development efficiency, that it helps us calculate how to update more efficiently during repeated renderings, rather than that it’s faster than DOM operations.

React implements its own event mechanism based on VitrualDom, simulates the process of event bubble and capture, adopts event proxy, batch update and other methods, and eliminates the event compatibility problems of various browsers.

Realize the principle of

  • React component rendering process
  1. When you write a React component using either React. CreateElement or JSX, virtually all JSX code ends up being converted to React. CreateElement (…) , Babel helped us complete the transformation process.

  2. The createElement function handles special props such as key and ref, gets the defaultProps, assigns the defaultProps, and processes the child nodes passed in. Finally, it constructs a ReactElement object (the so-called virtual DOM).

  3. ReactDOM. Render renders the generated virtual DOM to the specified container, which adopts batch processing, transaction and other mechanisms and optimizes the performance of specific browsers, and finally converts it into real DOM

  • Components of the Virtual DOM
  • Prevent XSS: use Symbol. For (‘react. Element ‘)
  • Batch and transaction mechanism: setState
  • Targeted performance optimization: IE/Edge Fragment
  • Event mechanism: I implemented an event mechanism that maps all events bound to the virtual DOM to real DOM events andProxy all events to the Document,The process of event bubble and capture is simulatedAnd unified event distribution.