A, components,

1. Pure components

React.PureComponent, like react.component. defines a component class. The difference is that shouldComponentUpdate() is not implemented. React.purecomponent is implemented via a shallow comparison of props and state.

// react. PureComponent Pure components
class Counter extends React.PureComponent {
  constructor(props) {
    super(props);
    this.state = {count: 0};
  }
  render() {
    return (
      <button onClick={()= > this.setState(state => ({count: state.count + 1}))}>
        Count: {this.state.count}
      </button>); }}Copy the code

More on this in the next section.

2. Function components

The easiest way to define a React component is to define a function component that accepts a single props and returns a React element.

// Function components
function Counter(props) {
    return <div>Counter: {props.count}</div>
}
/ / class components
class Counter extends React.Component {
  render() {
    return <div>Counter: {this.props.count}</div>}}Copy the code
  • In a function component, its input and output are all determined by props without any side effects, indicating that it is also stateless.
  • In a function component, functions cannot be modified, state cannot be used, and the lifecycle of the component cannot be used, indicating that the function component is also a presentation component.
  • The function component’s function is just to receive props, render the page, it doesn’t do any uI-independent logic, it’s just a pure function.
  • Function components are much more compact than class components. Both reusability and performance are superior to class components.

3. Controlled components and uncontrolled components

Controlled or uncontrolled depends primarily on whether the component is controlled by the props passed in by the parent

If the data is passed in by props, the component can be considered controlled (because the component is controlled by the parent’s props).

Data stored only in state within a component is an uncontrolled component (because there is no direct external control of state).

export default class AnForm extends React.Component {
  state = {
    name: ""
  }
  handleSubmitClick = (a)= > {
    console.log("Uncontrolled components:".this._name.value);
    console.log("Controlled Components:".this.state.name);
  }
  handleChange = (e) = > {
    this.setState({
      name: e.target.value
    })
  }

  render() {
    return<form onSubmit={this.handleSubmitClick}> <label> <input type="text" defaultValue="default" ref={input => this._name = input} /> </label> <input type="text" value={this.state.name} onChange={this.handleChange} /> </label> <input type="submit" value="Submit" /> </form> ); }}Copy the code
The controlled components

Unlike HTML, in React, components such as or < SELECT > or

export default class AnForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {value: ""};
    this.handleChange = this.handleChange.bind(this);
  }
  handleChange(event) {
    this.setState({value: event.target.value});
  }
  render() {
    return <input 
      			type="text" 
      			value={this.state.value} 
      			onChange={this.handleChange} 
      		/>; }}Copy the code
  • OnChange & Value mode (Radio buttons and check buttons correspond to Checked props)

  • React eliminates local component state in this way, making the entire state of the application manageable.

  • Note that is an uncontrolled component.

  • Multiple similar operations can be combined into one using the computed property name.

    this.setState({
      [name]: value
    });
    Copy the code
Uncontrolled component

Instead of storing data in state, uncontrolled components use refs to store real data in the DOM.

export default class AnForm extends Component {
  handleSubmitClick = (a)= > {
    const name = this._name.value;
  }

  render() {
    return (
      <div>
        <input type="text" ref={input= > this._name = input} />
        <button onClick={this.handleSubmitClick}>Sign up</button>
      </div>); }}Copy the code
  • Uncontrolled components are the easiest and fastest way to implement them, and are used for minimalist forms in a project, but controlled components are the most authoritative.

  • Usually specify a defaultValue/defaultChecked default value to control the initial state, do not use value.

  • Uncontrolled components can integrate React and non-React code more easily than controlled components.

  • Usage scenarios

    Characteristics of the Uncontrolled component The controlled components
    one-time value retrieval (e.g. on submit)
    validating on submit
    instant field validation
    conditionally disabling submit button
    enforcing input format
    several inputs for one piece of data
    dynamic inputs

4. Stateful and stateless components

Stateful component

Manage status through state

export default class Counter extends React.Component {
  constructor(props) {
    super(props)
    this.state = { clicks: 0 }
    this.handleClick = this.handleClick.bind(this)
  }
  handleClick() {
    this.setState(state= > ({ clicks: state.clicks + 1 }))
  }
  render() {
    return (
      <Button
        onClick={this.handleClick}
        text={`You've clicked meThe ${this.state.clicks} times! `} / >)}}Copy the code
Stateless component

The input/output data is completely determined by props and has no side effects.

const Button = props =>
  <button onClick={props.onClick}>
    {props.text}
  </button>
Copy the code
  • Stateless components are typically used in conjunction with a higher-order component (HOC for short) that hosts state. The Redux framework manages data sources and all states through a store, where all components responsible for presentation are written stateless functions.
  • A simple stateless button component that only relies on props(properties), also known as a functional component.

5. Show components and container components

Display components

A presentation component is a component that does not care how data is loaded or changed, but only how the page is presented.

class TodoList extends React.Component{
    constructor(props){
        super(props);
    }
    render(){
        const {todos} = this.props;
        return (<div>
                <ul>
                    {todos.map((item,index)=>{
                        return <li key={item.id}>{item.name}</li>
                    })}
                </ul>
            </div>)}}Copy the code
  • Only props can be used to receive data and perform callbacks.
  • Few have their own state, and those that do are used to show UI state.
  • It is usually possible to include other components in this.props. Children mode.
  • The interior can contain presentation and container components, usually with some of their own DOM tags and styles.
  • There are no dependencies on other parts of the application, such as Flux operations or stores.
  • Is written as a functional component unless the component needs its own state, lifecycle, or performance tuning.
Container components

The container component only cares about how the data is loaded and changed, not how the page looks.

// Container components
class TodoListContainer extends React.Component{
    constructor(props){
        super(props);
        this.state = {
            todos:[]
        }
        this.fetchData = this.fetchData.bind(this);
    }
    componentDidMount(){
        this.fetchData();
    }
    fetchData(){
        fetch('/api/todos').then(data= >{
            this.setState({
                todos:data
            })
        })
    }
    render(){
        return (<div>
                <TodoList todos={this.state.todos} />    
            </div>)}}Copy the code
  • The interior can contain container components and presentation components, but usually doesn’t have any DOM tags of its own, except for some wrapped divs, and never has any styles.
  • Provide data and behavior to other presentation components or container components.
  • The Flux operations can be invoked and provided to the presentation component as callback functions.
  • They tend to be stateful because they tend to act as data sources
  • Typically generated using higher-order components such as React Redux’s Connect ()

6. Advanced components

Definition of higher-order functions: a class of functions that receive a function as input or output another function are called higher-order functions.

For higher-order components, it describes a component that takes the React component as input and outputs a new React component.

More popularly, a high-order component is passed in by wrapping the React component, which, after a series of processing, returns a relatively enhanced React component for other components to call. To make our code more reusable, logical and abstract, it can hijack the Render method and also control props and state.

There are two ways to implement higher-order components:

  • The higher-order components operate props through the wrapped React component.
  • Inheritance Inversion, a high-order component inherits from the packaged React component.
// Property proxy
export default function withHeader(WrappedComponent) {
  return class HOC extends React.Component { / / inheritance and React.com ponent
    render() {
      const newProps = {
        test:'hoc'
      }
      // Pass through props, and pass the new newProps
      return <div>
        <WrappedComponent {. this.props} {. newProps} / > 
      </div>Export default Function (WrappedComponent) {return class Inheritance extends WrappedComponent {// Inheriting from the wrapped React component componentDidMount() {// It's easy to get state and make some further changes. console.log(this.state); } render() { return super.render(); }}}Copy the code
  • Note: Do not modify a component’s prototype (or otherwise modify the component) in HOC
  • Passing unrelated props properties to wrapped components throughout helps ensure maximum flexibility and reusability for higher-order components
  • Maximized compositability should be used
  • To facilitate debugging, select a display name that communicates that it is the result of a higher-order component,WrappedComponent.displayName || WrappedComponent.name || 'Component';
  • Do not create HOC in the Render () method, or render HOC will be recreated with every render
  • The static methods of the original component must be copied in HOC, otherwise HOC will not have any static methods of the original component
  • Refs cannot pass through the forwardRef property

7. Hook component

Hook is a new feature in React 16.8. It lets you use state and other React features without having to write a class.

But unlike a class life cycle, hooks are closer to achieving state synchronization than to responding to life cycle events.

import React, { useState, useEffect } from 'react';

function Example() {
  // Declare a state variable called "count"
  const [count, setCount] = useState(0);
    
  useEffect((a)= >{
    // What needs to be executed at componentDidMount
    return function cleanup() {
      // What needs to be executed at componentWillUnmount
  	}
  }, [])

  useEffect((a)= > { 
    // What componentDidUpdate executes when componentDidMount and count changes
    document.title = 'You clicked ' + count + ' times'; 
    return (a)= > {
      // componentDidUpdate (prior to document.title =... Clean up before updating)
      // And what componentWillUnmount executes
    } The Cleanup function is executed in the order defined in the code, regardless of the function's nature
  }, [count]); // Update only when count changes

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={()= > setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}
Copy the code
  • The Hooks component is closer to implementing state synchronization than to responding to life cycle events
  • A Hook can only be called on the outermost layer of a function. You can only call a Hook in the React function component.
  • useLayoutEffect 与 componentDidMount,componentDidUpdateThe call phase is the same. However, we recommend youStart with useEffectTry using it only when something goes wronguseLayoutEffect
  • withcomponentDidMount 或 componentDidUpdateThe difference is that hooks do the layout and drawing in the browserafterAnd send it touseEffectIs delayed, but is guaranteed to be executed before any new rendering
  • An effect cleanup does not read the “latest” props. It can only read the props value in the render in which it was defined
  • The latest count state value can be read in effect. It is not that the value of count has changed in the “unchanged” effect, but that the effect function itself is different from one render to another
  • In the class component lifecycle mindset, side effects behave differently than render outputs. UI rendering is powered by props and state and ensures consistency, but side effects are not. This is a common source of problems.
  • And in theuseEffectBy default, they are all synchronized. Side effects become part of the React data flow. For each of themuseEffectOnce you get it right, your component is better able to handle edge cases.

Component source code interpretation

First take a look at the React.Component structure

/ / ReactBaseClasses. Js file
/** * Base class helpers for the updating state of a component. */
function Component(props, context, updater) {
  this.props = props; / / properties props
  this.context = context; // Context context
  // If a component has string refs, we will assign a different object later.
  // Initialize refs to {}, mainly used in stringRef, to mount instances of the stringRef node on this.refs
  this.refs = emptyObject; 
  // We initialize the default updater but the real one gets injected by the
  // renderer.
  this.updater = updater || ReactNoopUpdateQueue; // updater
}

Component.prototype.isReactComponent = {};

/* shouldComponentUpdate 'shouldComponentUpdate' is a shallow update, * Mutable types may cause 'shouldComponentUpdate' to return false and cannot be re-rendered * Immutable. It provides non-mutable, durable sets through structural sharing: * Non-mutable: Once created, the set cannot be changed at another point in time. Persistence: You can use the original collection and a mutation to create a new collection. The original collection is still available after the new collection is created. * Structure sharing: New collections are created using as much of the original collection's structure as possible to minimize duplication and improve performance. * * does not guarantee that 'this.state' cannot be mutageable after passing 'setState', It may return the same value * there is no guarantee that 'setrState' will update synchronously. 'this.state' * 'setState' updates state in a queue. * the state is shallow merged into the status queue and executed in batches, meaning it is not immediately updated. * However, you can get the latest value in the callback function * * Note: For asynchronous rendering, We should read 'state', 'props' in' getSnapshotBeforeUpdate ', * * @ * rather than ` componentWillUpdate ` param {object | function} partialState Next partial state or function to * produce Next partial state to be merged with current state. * @param {? function} callback Called after state is updated. * @final * @protected */
Component.prototype.setState = function(partialState, callback) {
  // When partialState is object or function or null,
  / / perform this. Updater. EnqueueSetState method, otherwise an error
  invariant(
    typeof partialState === 'object' ||
      typeof partialState === 'function' ||
      partialState == null.'setState(...) : takes an object of state variables to update or a ' +
      'function which returns an object of state variables.',);// Queue the setState transaction
  this.updater.enqueueSetState(this, partialState, callback, 'setState'); 
};

/** * Force update, Invoked only if and only if not currently in a DOM transaction * This should only be invoked when it is known with * certainty that we are **not** * * By default, the component will be re-rendered when its state or props changes. * If your 'render()' method depends on some other data, * you can tell the React component that it needs to re-render by calling 'forceUpdate()'. Calling 'forceUpdate()' causes the component to skip 'shouldComponentUpdate()' and call 'render()' directly. But 'componentWillUpdate' and 'componentDidUpdate' are called. * This triggers the normal lifecycle methods of the component, including the shouldComponentUpdate() method for each child component. * forceUpdate is rerender. * Refresh render when you want to update a variable that is not in state; * Or a variable in state is so deep that it doesn't automatically trigger render when updated. * You can manually call forceUpdate to automatically trigger render * * @param {? * @final * @protected */
Component.prototype.forceUpdate = function(callback) {
  // updater forces update
  this.updater.enqueueForceUpdate(this, callback, 'forceUpdate'); 
};
Copy the code

Where this.refs emptyObject is:

// set refs to {}
const emptyObject = {};
if (__DEV__) {
  Object.freeze(emptyObject); // In __DEV__ mode, freeze emptyObject
}
// object.freeze () Freezes an Object. The frozen Object cannot be modified (added, deleted,
// Modify the enumerability, configurability, writability and attribute values of existing attributes, prototype); Returns the same object as the argument passed in.

Copy the code

ReactNoopUpdateQueue as follows:

/ / ReactNoopUpdateQueue. Js file
/** * This is an abstract API for update queues */
const ReactNoopUpdateQueue = {
  * @param {ReactClass} publicInstance test instance unit * @return {Boolean} Load complete is true, Otherwise false * @protected * @final */
  isMounted: function(publicInstance) {
    return false;
  },

  /** * Forces the update queue to be invoked if and only if it is not currently in a DOM transaction ** When a variable in state is too deep, the update does not automatically trigger render. * this method will skip 'shouldComponentUpdate()' and call 'render()', But it will call up * 'componentWillUpdate' and 'componentDidUpdate'. * * @param {ReactClass} publicInstance will be re-rendered instance * @param {? * @param {? String} callerName Specifies the name of the function that calls this method on the public API
  enqueueForceUpdate: function(publicInstance, callback, callerName) {
    warnNoop(publicInstance, 'forceUpdate');
  },

  /** * completely replaces state. Unlike setState, setState changes state in a modified and new way. * does not change state that is not involved. * And 'enqueueReplaceState' completely replaces the old 'state' with the new 'state' * use it or 'setState' to change the state, and this. State should be set to an unmutable object, * We should get The latest state in callback * * @param {ReactClass} publicInstance The instance that should rerender. * @param {object} completeState Next state. * @param {? function} callback Called after component is updated. * @param {? string} callerName name of the calling function in the public API. * @internal */
  enqueueReplaceState: function(publicInstance, completeState, callback, callerName,) {
    warnNoop(publicInstance, 'replaceState');
  },

  /** * Sets a subset of state * the only reason it exists is because _pendingState is an internal method. * 'enqueueSetState' implements shallow merge update 'state' * * @param {ReactClass} publicInstance The instance that should rerender. * @param {object} partialState Next partial state to be merged with state. * @param {? function} callback Called after component is updated. * @param {? string} Name of the calling function in the public API. * @internal */
  enqueueSetState: function(publicInstance, partialState, callback, callerName,) {
    warnNoop(publicInstance, 'setState'); }};export default ReactNoopUpdateQueue;
Copy the code

The React API is implemented in the React DOM. This is because the React API is the same for different platforms, but the rendering process is different for different platforms. The specific Component rendering process is different, and will be customized according to the specific platform.

Component life cycles refer to the relationship between Hooks and React life cycles

series

For more on this series,Click on the Github homepage

Go last, welcome to pay attention to: front-end bottle jun, daily update