The difference between props and state

  • props

Property Read-only External interface of the component

  • state

The internal interface of a variable state component

Do not use push, POP, Shift, unshift, splice, etc., to change the state of the array type, because these methods are based on the original array, while concat, slice, filter return a new array.

The difference between passing an object to setState and passing a function

Because setState merges updates asynchronously, setState passes an object, and if we update states that depend on the current state, we can’t be sure that each call is the latest state, giving us the wrong value. Passing a function can access the value of the current state in the function, ensuring that they are built on top of the other

The way code is split

  1. import()
  2. React.lazy
  3. Exception capture boundary
  4. React. Lazy and React Router third-party libraries to configure route-based code splitting

What is HOC?

HOC is an advanced technique used in React to reuse component logic.

A higher-order component is a function that takes a component and returns a new component.

Examples are Redux’s Connect and Relay’s createFragmentContainer.

// This function accepts a component... function withSubscription(WrappedComponent, selectData) { // ... And returns another component... return class extends React.Component { constructor(props) { super(props); this.handleChange = this.handleChange.bind(this); this.state = { data: selectData(DataSource, props) }; } componentDidMount() { // ... Responsible for subscription related operations... DataSource.addChangeListener(this.handleChange); } componentWillUnmount() { DataSource.removeChangeListener(this.handleChange); } handleChange() { this.setState({ data: selectData(DataSource, this.props) }); } render() { // ... And render the wrapped component with the new data! Return <WrappedComponent data={this.state.data} {... this.props} />; }}; }Copy the code
const CommentListWithSubscription = withSubscription(
  CommentList,
  (DataSource) => DataSource.getComments()
);

const BlogPostWithSubscription = withSubscription(
  BlogPost,
  (DataSource, props) => DataSource.getBlogPost(props.id)
);
Copy the code

Matters needing attention

  • Do not use HOC in render methods

The React diff algorithm (called coordination) uses component identifiers to determine whether it should update an existing subtree or drop it and mount a new one. If the component returned from Render is the same as the component in the previous render (===), React updates the subtree recursively by differentiating it from the new one. If they are not equal, the previous subtree is completely unloaded.

This isn’t just a performance issue – remounting a component causes a loss of state for that component and all its children.

In rare cases, you need to invoke HOC dynamically. You can make the call in a component’s lifecycle method or in its constructor.

  • Be sure to copy static methods

When you apply HOC to a component, the original component is wrapped with a container component. This means that the new component does not have any static methods of the original component.

/ / define static function WrappedComponent. StaticMethod = function () {/ *... */} // Now use HOC const EnhancedComponent = enhance(WrappedComponent); . / / enhancement components without staticMethod typeof EnhancedComponent staticMethod = = = 'undefined' / / trueCopy the code
  1. Automatically copy all non-React static methods using hoist-non-react-statics
import hoistNonReactStatic from 'hoist-non-react-statics'; function enhance(WrappedComponent) { class Enhance extends React.Component {/*... */} hoistNonReactStatic(Enhance, WrappedComponent); return Enhance; }Copy the code
  1. Export this static method in addition
// Use this method instead of... MyComponent.someFunction = someFunction; export default MyComponent; / /... Export the method separately... export { someFunction }; / /... Import MyComponent, {someFunction} from './ myComponent.js ';Copy the code
  • Refs will not be passed

Ref is not actually a prop- like key, it is handled specifically by React. If you add ref to HOC’s return component, the REF reference points to the container component, not the wrapped component.

The Context and its API

Context provides a way to share such values between components without explicitly passing props layer by layer through the component tree. The main application scenario is that many components at different levels need to access the same data.

React. CreateContext: Creates a Context object.

const MyContext = React.createContext(defaultValue);

Context.Provider: Each Context object returns a Provider React component, which allows the consuming component to subscribe to changes to the Context.

< myContext. Provider value={/* some value */}>

Class.contexttype: The contextType property mounted on the Class is reassigned to a Context object created by react.createcontext ()

class MyClass extends React.Component { componentDidMount() { let value = this.context; } componentDidUpdate() {let value = this.context;} componentDidUpdate() {let value = this.context; / *... */ } componentWillUnmount() { let value = this.context; / *... */ } render() { let value = this.context; /* Render based on the value of MyContext component */}} myClass.contextType = MyContext;Copy the code

The Context.Consumer: React component can subscribe to Context changes

< mycontext.consumer > {value => /* Render based on the context value */} </ mycontext.consumer >Copy the code

DisplayName: The Context object accepts a property named displayName of type string.

const MyContext = React.createContext(/* some value */); MyContext.displayName = 'MyDisplayName'; Provider < myContext. Provider> // "myDisplayName. Provider" in DevTools < myContext. Consumer> //" myDisplayName. Consumer" in In the DevToolsCopy the code

Refs forward

Ref forwarding is a technique for automatically passing a Ref through a component to one of its children.

const FancyButton = React.forwardRef((props, ref) => ( <button ref={ref} className="FancyButton"> {props.children} </button> )); DOM button ref: const ref = react.createref (); <FancyButton ref={ref}>Click me! </FancyButton>;Copy the code

Forwarding refs in higher-order components

function logProps(Component) { class LogProps extends React.Component { componentDidUpdate(prevProps) { console.log('old  props:', prevProps); console.log('new props:', this.props); } render() { const {forwardedRef, ... rest} = this.props; // define the custom prop property "forwardedRef" as ref return <Component ref={forwardedRef} {... rest} />; }} // the forwardRef callback is called by the forwardRef callback. // We can pass it as a regular prop property to LogProps, such as "forwardedRef" // then it can be mounted to a child component wrapped by LogProps. return React.forwardRef((props, ref) => { return <LogProps {... props} forwardedRef={ref} />; }); }Copy the code

What is a Portal

Portal provides an excellent solution for rendering child nodes to DOM nodes that exist outside the parent component.

ReactDOM.createPortal(child, container)
Copy the code

The first argument (child) is any renderable React child element, such as an element, string or fragment. The second argument (container) is a DOM element.

What is the Profiler

Profiler measures how often a React application is rendered and the “cost” of rendering once.

Note: Profilers add additional overhead and should be used only when needed.

It requires two prop: the ID (string) and the onRender(function) callback called when a component of the React tree “commits” an update.

Each prop of onRender function:

  • Id: string – THE ID of the Profiler tree on which the commit occurred. If there are multiple profilers, it can be used to identify which part of the tree “commits” occurred.
  • Phase: “mount” | “update” – judgment is the first time that the component tree load caused by heavy rendering, or by the props, the state or hooks changes caused by heavy rendering.
  • ActualDuration: Number – The amount of time this update takes to render the Profiler and its descendants. This number shows how well you can perform with Memoization. (e.g. React.memo, useMemo, shouldComponentUpdate). Ideally, this value should drop significantly after the first load, since children are only rerendered for specific prop changes.
  • BaseDuration: Number – Duration of last render of each component in the Profiler tree. This value estimates the worst render time. (such as when it is first loaded or when the component tree is not memoization).
  • StartTime: Number – The time stamp used by React to start rendering.
  • CommitTime: Number – The timestamp at the end of the React Commit phase in this update. This value is shared among all profilers during a commit and can be grouped as needed.
  • Interactions: Set – When updates are made, the Set of “Interactions” is tracked. (e.g., when render or setState is called).

Performance optimization

  1. Use the production version
  2. Single-file build
  3. Get the most efficient Brunch production build by installing the Terser-Brunch plug-in
  4. Use the Chrome Performance TAB to analyze components
  5. Analyze components using profilers in developer tools
  6. Virtualization Long List (react-windowandreact-virtualized)
  7. The optimization of shouldComponentUpdate
  8. The power of immutable data

React defines components in three ways

  • Stateless functional component To create a pure presentation component, this component is only responsible for presenting according to the props passed in and does not involve the operations to be state

    Features:

    1. Components are not instantiated and overall rendering performance is improved
    2. Component not accessiblethisobject
    3. The component cannot access life-cycle methods
    4. Stateless components can only access inputprops, the samepropsYou get the same render results, with no side effects
  • React.createClass

React. CreateClass is the first recommended way to create components in React. This is implemented in ES5 using native JavaScript

Problems: 1. 'React. CreateClass' will self-bind function methods (unlike react.component, which only binds functions of interest), resulting in unnecessary performance overhead and increasing the likelihood of stale code. 2. 'React. CreateClass' mixins are not natural and intuitive; The 'react.component-based' form is well suited to Higher Order Components (HOC), which shows more power than mixins in a more intuitive form, and HOC is pure JavaScript, so don't worry about them being obsolete.Copy the code
  • React.Component

React.componentcreates react components in ES6 format, which is the most recommended way to create stateful components in React

React.ponent differs from react.createclass

  • Declare the default properties differently

Either a function component or a class component has the defaultProps property:

class Greeting extends React.Component {
  // ...
}

Greeting.defaultProps = {
  name: 'Mary'
};
Copy the code

If you use the React. CreateClass method to create a component, you need to define the getDefaultProps() function in the component:

const Greeting = React.createClass({ getDefaultProps: function() { return { name: 'Mary' }; } / /... });Copy the code
  • Different initialization states

If you create a component using the ES6 class keyword, you can define the initial state of the component by assigning this. State:

class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = {count: props.initialCount};
  }
  // ...
}
Copy the code

If you use the React. CreateClass method to create a component, you need to provide a separate getInitialState method that returns the initial state:

const Counter = React.createClass({ getInitialState: function() { return {count: this.props.initialCount}; } / /... });Copy the code
  • Automatically bind this

React.Com ponent created component, its member function does not automatically binding this, need to manually bind developers

There are three manual binding methods:

  1. The binding is done in the constructor
constructor(props) { super(props); this.handleClick = this.handleClick.bind(this); // bind in constructor}Copy the code
  1. Use method.bind(this) at call time to complete the binding
<div onClick={this.handleclick. bind(this)}></divCopy the code
  1. Use arrow Function to bind
<div onClick={()=> this.handleclick ()}></div> // use arrow functionCopy the code

React. CreateClass creates a component whose this is automatically bound to React for each of its member functions

  • React.createClassSupport Mixins, whileReact.ComponentDoes not support

Mixins(Mixins) is an implementation of OOP. Its function is to reuse common code. The common code is extracted as an object, and then into the object through Mixins to achieve code reuse.

var SetIntervalMixin = { componentWillMount: function() { this.intervals = []; }, setInterval: function() { this.intervals.push(setInterval.apply(null, arguments)); }, componentWillUnmount: function() { this.intervals.forEach(clearInterval); }}; var createReactClass = require('create-react-class'); Var TickTock = createReactClass({mixins: [SetIntervalMixin], // use mixin getInitialState: function() { return {seconds: 0}; }, componentDidMount: function() { this.setInterval(this.tick, 1000); }, tick: function() {this.setState({seconds: this.state.seconds + 1}); }, render: function() { return ( <p> React has been running for {this.state.seconds} seconds. </p> ); }}); ReactDOM.render( <TickTock />, document.getElementById('example') );Copy the code

Diffing algorithm

  • Compare different types of elements

When the root node has a different type of element, React disassembles the existing tree and creates a new one.

  • Compare elements of the same type

When comparing two React elements of the same type, React preserves the DOM node and only compares and updates the changed attributes.

  • Compare component elements of the same type

When a component is updated, the component instance remains the same, so that state remains consistent across different renderings

  • Recurse on the child nodes

By default, React iterates through lists of both child elements while recursively iterating through the child elements of a DOM node. When a difference occurs, a mutation is generated. When new elements are added at the end of the child element list, the update overhead is low. Such as:

<ul>
  <li>first</li>
  <li>second</li>
</ul>

<ul>
  <li>first</li>
  <li>second</li>
  <li>third</li>
</ul>
Copy the code

React matches two

  • first
  • trees, then matches the second< li>second tree, and finally inserts the

  • third
  • tree of the third element.

    If you simply insert the new element into the table header, the update will be expensive. Such as:

    <ul>
      <li>Duke</li>
      <li>Villanova</li>
    </ul>
    
    <ul>
      <li>Connecticut</li>
      <li>Duke</li>
      <li>Villanova</li>
    </ul>
    Copy the code

    React will not realize that it should keep

  • Duke
  • and

  • Villanova
  • , but will rebuild each child element. This situation can cause performance problems.

    To address these issues, React supports the key attribute. When a child element has a key, React uses the key to match the child element of the original tree with the child element of the latest tree.

    <ul>
      <li key="2015">Duke</li>
      <li key="2016">Villanova</li>
    </ul>
    
    <ul>
      <li key="2014">Connecticut</li>
      <li key="2015">Duke</li>
      <li key="2016">Villanova</li>
    </ul>
    Copy the code

    React now knows that only elements with the ‘2014’ key are new; elements with the ‘2015’ and ‘2016’ keys are simply moved.

    What are Render Props

    The e term “Render Prop” refers to a simple technique for sharing code between React components using a prop with a value of function. A component with Render Prop takes a function that returns the React element and implements its own rendering logic within the component by calling this function.

    <DataProvider render={data => (
      <h1>Hello {data.target}</h1>
    )}/>
    Copy the code

    More specifically, Render Prop is a function prop that tells components what to render.

    Most high-level components (HOC) can be implemented using regular components with Render Prop.

    Typescript gets a library declaration file

    To be able to display errors and prompts from other packages, the compiler relies on the declaration file. The declaration file provides all type information about the library.

    • Bundled: This library contains its own declaration files.
    • DefinitelyTyped: Is a huge declaration repository that provides type definitions for JavaScript libraries that have no declaration files. These type definitions are crowdsourced and managed by Microsoft and open source contributors.
    npm i --save-dev @types/react
    Copy the code
    • Local declarations: Sometimes the package you are using does not have a declaration file init, nor on DefinitelyTyped. In this case, we can create a local definition file.

    What are controlled components and uncontrolled components

    • Controlled Components: Data is managed by the React component
    • Uncontrolled components: Data is handed over to DOM nodes for processing (using Ref).