Introduction of the React

React is a JavaScript library that Facebook opened source in 2013. It abstracts the interface into components, and by combining these components, developers can get rich pages. JSX syntax is also introduced, making it easy to reuse components and clear structure. And with the component level of abstraction, the code is separated from the real rendering goal and can be used for native mobile application development in addition to browser side rendering to DOM development web pages.

Focus view layer

React is not a complete MVC/MVVM framework, it focuses on the View layer solution. Unlike the template engine, React is a library that includes views and controllers.

Virtual DOM

React converts a real DOM tree into a JavaScript object tree, the Virtual DOM. At each data update, the Virtual DOM before and after the data update is compared, and the changed parts are updated in batches to improve performance. In addition, Virtual DOM can be easily integrated with other platforms. For example, React-Native is based on Virtual DOM to render native controls.

Functional programming

Imperative programming gives names to computers, and functional programming, which corresponds to declarative programming. The essence of declarative programming is lambda calculus, where we operate on each element of an array and return a new array. What we do is we build an f function (rule) that we apply to an array, and then we return the new array. In this way, calculations can be reused.

JSX grammar

JSX is a language (syntax) created by React to facilitate the componentization of the View layer and the responsibility of building HTML structured pages.

DOM elements and component elements

Virtual elements created in React fall into two categories: DOM elements and Component elements. Corresponds to a native DOM element and a custom element, respectively.

DOM elements

When using JavaScript to describe HTML elements of a Web page, they can be represented as pure JSON objects. For example, describe a button

<button class="btn btn-blue">
  <em>Confirm</em>
</button>
Copy the code

->

{
  type: 'button',
  props: {
    className: 'btn btn-blue',
    children: [{
      type: 'em',
      props: {
        children: 'Confirm'}}}}]Copy the code

Elements everywhere in React are not real instances, they are just description objects for the page.

The component element

React can also customize component elements. Analogy is as follows

const Button = ({ color, text }) = > {
  return {
    type: "button".props: {
      className: `btn btn-${color}`.children: [{type: "em".props: {
            children: text
          }
        }
      ]
    }
  };
};
Copy the code

Button can also exist as an element. The method name corresponds to the element type, and the parameter corresponds to the element attribute. This is also one of the core ideas of React. We can make DOM elements and component elements nested and combined, and finally build a complete DOM element tree by recursive rendering. But this writing is not easy to read and maintain, and the JSX syntax is where it comes in.

const Button = ({ color, text }) => {
  <button className={`btn btn-${color}`}>
    <em>{text}</em>
  </button>;
};
Copy the code

JSX adds HTML syntax directly to JavaScript code, which is then converted by a translator into pure JavaScript for execution by the browser.

JSX basic syntax

The official definition of JSX is an ECMAScript extension to xmL-like syntax.

Basic XML syntax

Using XML-like syntax, we can clearly see the DOM tree result and its attributes. It’s just wrapped in JavaScript methods

const List = (a)= > (
  <ul>
    <li>1</li>
    <li>2</li>
  </ul>
);
Copy the code

A few things to note

  1. When a label is defined, it can be wrapped by only one label. Such as
const c = (a)= > (<span>1</span><span>2</span>);
Copy the code

The outermost no complains, package, obviously cannot be translated into the React. CreateElement method method call

  1. The label must be closed, for example<div></div>,<div />

The element type

In addition, there are some special tags worth discussing, such as annotations and DOCTYPE headers. JSX is still JavsScript, and you can still use annotations in a simple way, with annotations wrapped in {} at the child element location. For conditional comments that are often used to determine browser versions

<! - [if IE]>
  <p>work inIE</p> <! [endif]-->Copy the code

JavaScript judgment is needed to implement this

{(!!!!! window.ActiveXObject ||'ActiveXObject' in window) ?
  <p>work in IE</p> : ' '
}
Copy the code

The DOCTYPE header is a very special flag that is usually used when the React server renders. The DOCTYPE is not closed and we cannot render it. A common practice is to construct a variable that holds the HTML and concatenate the DOCTYPE with the rendered result of the entire HTML tag.

Element attributes

DOM element attributes are standard specification attributes, but class and for are keywords, replaced by className and htmlFor. Component element attributes are fully custom properties that can also be understood as parameters required to implement the component. The small hump is usually used. In addition, there are some unique attribute expressions

  1. Omitting the Boolean property value causes JSX to consider the bool value set to true
<Checkbox checked={true} / >Copy the code

I can write this for short

<Checkbox checked />
Copy the code
<Checkbox checked={false} / >Copy the code

Can be omitted as

<Checkbox />
Copy the code
  1. Use the ES6 REST /spread feature to improve development efficiency
const data = { name: "foo".value: "bar" };
const component = <Component {. data} / >;
Copy the code
  1. Custom HTML attributes pass custom attributes to DOM elements, but React does not render them
<div d="xxx">content</div>
Copy the code

The data- prefix is required, which is also consistent with the HTML standard

<div data-attr="xxx">content</div>
Copy the code

In a custom tag, however, any attribute is supported

<CustomComponent d="xxx" />
Copy the code
  1. JavaScript attribute expressions
<Person name={true ? 1 : 2} / >Copy the code
  1. React will escape all strings to be displayed in the DOM, preventing XSS. Such as&copy;It will not display correctly. The solution is as follows: 1. Use UTF-8 characters directly. 2. Assembly using the work array<div>{['cc ', <span>&copy;</span>, ' 2015']}</div>4. Insert the original HTML directly

React also provides dangerouslySetInnerHTML attributes. It avoids React escape characters, so use it if you’re sure it’s necessary

<div dangerouslySetInnerHTML={{ __html: "cc &copy; 2015"}} / >Copy the code

The React components

Evolution of components

Before the MVC architecture, there were two main types of components

  1. Components in a narrow sense, also known as UI components, mainly focus on the abstraction of interactive actions, using JavaScript manipulation of DOM structure or style style to control
  2. Components in a broad sense, a combination of UI components with business meaning and data. It prefers a hierarchical approach to UI components, divided into three parts: structure, style, and interaction, corresponding to HTML, CSS, and JavaScript.

The basic idea of encapsulation is object – oriented. The interaction is basically to manipulate the DOM. The logic is that where the structure needs to change, we operate on it. The following is information about several canonical standard components.

  1. Basic encapsulation. Although JavaScript has no true object-oriented approach, we can still create objects by instantiating them.
  2. Simple life cycle presentation. Contructor and Destroy, for example, represent the mounting and unmounting of components.
  3. Clear data flow. The data here refers to the parameters of the calling component. Once the value of the parameter is determined, the passed parameter is parsed and the response is made according to the different parameters.

At this stage, the front end does not have too many complex interactions at the application level. The main problem with traditional components is that structure, style, and behavior are not well combined. Logic in different parameters can lead to different rendering logic, which can lead to a large amount of HTML structure and style style assembly. Once the logic is complex, development and maintenance costs are high.

So the idea of layering was introduced, and MVC architecture emerged. Views are only concerned with how to output variables, hence the creation of various template languages. Having the template itself host the logic can help solve the logic problems on the View. For components, you can decouple the logical parts of the assembled HTML, solving the problem of coupling data to the interface.

As a DSL, templates have their limitations. In Angular, we see how directives are defined in HTML.

The W3C has developed similar ideas into specifications called Web Components. It unifies components by defining Custom Elements. Each custom element can define its own externally provided properties, methods, and events, and can be written as a page, focusing on implementing functionality to complete the encapsulation of the component.

Web Components are made up of four Components: HTML Templates define the previous concept of Templates, Custom Elements define how a component will appear, Shadow DOM defines the scope of a component and the styles it can contain, and HTML Imports introduce new ways of introducing it.

In fact, it will take time. Because of things like how to wrap frameworks around this specification, how to get full support on the browser side, how to integrate with modern application architectures, and so on. But it does open up a Roman avenue to show us how componentization can be done.

Build the React component

React components are component elements. Component elements are described as pure JSON objects, meaning they can be built using methods or classes. The React component is basically made up of three parts – props, states, and lifecycle methods.

The React component can receive parameters and may have its own state. As soon as the received parameters or state changes, the React component executes the corresponding lifecycle method and finally renders.

From the perspective of React component, it is consistent with the idea conveyed by Web Components, but the two implementations are different:

  1. React custom elements are built by the library itself and are not common to the Web Components specification.
  2. The React rendering process includes the concept of templates, known as JSX
  3. React components are implemented in methods and classes, so they can be isolated from each other, but not styles.
  4. React references follow the ES6 Module standard

React works hard with pure JavaScript, completely introducing HTML structures into JavaScript. This approach has mixed reviews, but it effectively solves one of the problems that components are intended to solve.

The React component is basically composed of the component’s build mode, property state and lifecycle methods within the component.

The React component is built in three different ways :React. CreateClass, ES6 classes, and stateless functions.

CreateClass Building components with React. CreateClass is the most traditional and compatible approach to React.

const Button = React.createClass({
  getDefaultProps() {
    return {
      color: "blue".text: "Confirm"
    };
  },

  render() {
    const { color, text } = this.props;

    return (
      <button className={`btn btn-The ${color} `} >
        <em>{text}</em>
      </button>); }});Copy the code

ES6 classes is written using the ES6 standard class syntax to construct methods:

import React, { Component } from "react";

class Button extends Component {
  contructor(props) {
    super(props);
  }

  static defaultProps = {
    color: "blue".text: "Confirm"
  };

  render() {
    const { color, text } = this.props;

    return (
      <button className={`btn btn-The ${color} `} >
        <em>{text}</em>
      </button>); }}Copy the code

As with createClass, the component that calls the class implementation creates the instance object.

It’s easy to think of inheritance as an approach to component abstraction. In practice, we rarely allow subclasses to inherit functional components. Inheritance touches the whole body. In React component development, the common approach is to break components down to reasonable granularity and synthesize business components in a composite manner.

Description: All components of React inherit from the top-level react.ponent class. The definition is very simple. We initialize the react.ponent method, declare props, context, refs, and so on, and define setState and foreUpdate methods on the prototype. The internally initialized lifecycle method is created using the same method as the createClass method.

Stateless functions Components built using stateless functions are called stateless components

function Button({ color = "blue", text = "Confirm" }) {
  return (
    <button className={`btn btn-The ${color} `} >
      <em>{text}</em>
    </button>
  );
}
Copy the code

Stateless components only pass props and context; That is, it has no state, no lifecycle method, and the component itself is render in the above two React component build methods. However, things like propTypes and defaultProps can be implemented by setting static properties to methods.

Unlike the two methods above, a stateless component creates a new instance when invoked, it always maintains an instance when created, avoiding unnecessary checks and memory allocation.

The React data flow

In React, data flows one way from the top down, from the parent component to the child component.

State and props are the most important concepts in a component. If the top-level component initializes props, React will walk down the entire component tree and retry to render all related child components. State is concerned only with the internal state of the component itself, which can only be changed within the component. Think of the component as a function, with props as its argument, state as the function’s internal argument, and a Virtual DOM implementation returned.

state

In React, state is the internal state of the component. When a component uses the setState method internally, the component attempts to re-render.

It is important to note that setState is an asynchronous method, and all setState methods are merged over a lifetime.

If we think of a regular Tabs component, there are two different perspectives on activeIndex as state.

  1. Update internally. When we switch tabs, we can think of it as an interaction within the component that returns the selected index via a callback function.
  2. Update externally. When we switch tabs, we can think of the component as passing in a specific index, and the component is being manipulated like a puppet. These two situations are very common in the React component design, which we call the Smart component and the Puppet component, respectively

Of course, you can implement components that are compatible with both

constructor(props) {
  super(props);

  const currProps = this.props;

  let activeIndex = 0;
  // Source from external update
  if (activeIndex in currProps) {
    activeIndex = currProps.activeIndex;
    // Derived from using internal updates
  } else if ('defaultActiveIndex' in currProps) {
    activeIndex = currProps.defaultActiveIndex;
  }

  this.state = {
    activeIndex,
    prevIndex: activeIndex,
  };
}
Copy the code

props

Props is a mechanism that React uses to keep components connected to each other, just like method parameters.

The process of passing props is very intuitive for the React component. React’s main one-way data stream is props. Props itself is immutable. The props of a component must come from the default property or be passed through the parent component.

React provides a default configuration for props, defined as a static variable called defaultProps.

static defaultProps = {
  classPrefix: 'tabs'.onChange: (a)= >{}};Copy the code

Subcomponents prop

There is an important and built-in props in React — children, which represents the collection of children of a component.

The basic idea is to use a TabContent component to render a collection of TabPane child components as an example

getTabPanes() {
  const { classPrefix, activeIndex, panels, isActive } = this.props;

  return React.Children.map(panels, (child) => {
    if(! child) {return; }

    const order = parseInt(child.props.order, 10);

    return React.cloneElement(child, {
      classPrefix,
      isActive,
      children: child.props.children,
      key: `tabpane-${order}`}); }); }Copy the code

It iterates over the child components using the React.children. Map method, cloning the TabPane component using the React cloneElement method, and returning the TabPane component set.

React.Children is a series of methods to operate Children provided by React official. It provides utility functions such as map, forEach, count, and more. Using getTabPanes

render () {
  return (<div>{this.getTabPanes()}</div>);
}
Copy the code

Suppose we put the traversal of the child components from the this.getTabPanes method in the render method directly in

render() { return (<div>{React.Children.map(this.props.children, (child) => {... })}</div>) }Copy the code

This invocation is called Dynamic Children.

Component props

You can also pass child components as props. This is usually done by asking the developer to define a prop for a component with multiple types, allowing for a combination of simple configurations and custom configurations.

Communicate with parent using function Prop

this.props.onChange(activeIndex, prevIndex)
Copy the code

The onChange Prop callback is triggered to give the necessary values to the parent component.

propTypes

PropTypes is used to specify the types and required states of props. It checks the type of the component’s Prop value in the development environment.

static propTypes = {
  classPrefix: React.PropTypes.string,
}
Copy the code

PropTypes has many types supported, including not only basic types, but also enumerations and custom types.

React lifecycle

Mounting and unmounting processes

1. The process of mounting a component is mainly to initialize the component state. It is recommended to use the following example as a template to initialize the component:

import React, { Component, PropTypes } from 'react';

class App extends Component {
  static propTypes = {
    // ...
  }

  static defaultProps = {
    // ...
  }

  constructor(props) {
    super(props)

    this.state = {
      // ...
    }
  }

  componentWillMount() {
    // ...
  }

  componentDidMount() {
    // ...
  }

  render () {
    return <div>This is a demo</div>}}Copy the code

If we execute the setState method in componentWillMount, the component updates state, but the component only renders once. Thus, this is a meaningless execution that could have been placed in constructor initialization state. If we execute the setState method in componentDidMount, the component will be updated again, but the component will be rendered twice during initialization, which is not a good thing. But in practice, there are scenarios where this is necessary, such as when you need to get the location of a component. 2. ComponentWillUnmount, we often perform some cleaning methods, such as event recovery, clear timer.

Data update process

An update process is a series of update actions that occur when the parent passes the props down or when the component itself executes the setState method.

import React, { Component, PropTypes } from 'react'

class App extends Component {
  componentWillReceiveProps(nextProps) {
    // this.setState({})
  }

  shouldComponentUpdate(nextProps, nextState) {
    // return true
  }

  componentWillUpdate(nextProps, nextState) {

  }

  componentDidUpdate(prevProps, prevState) {

  }

  render() {

  }
}
Copy the code

If a component’s own state is updated, shouldComponentUpdate, componentWillUpdate, Render, and componentDidUpdate are executed in turn

ShouldComponentUpdate accepts props and states that need to be updated, allowing developers to add logic to the function and return false without updating the method. This is one of the ways to optimize performance.

Stateless components have no lifecycle methods, which means they have no shouldComponentUpdate. Render the class component, which is rerendered each time.

The componentWillUpdate method provides props and state to be updated, while The componentDidUpdate method provides props and state before the update.

Note that the setState method cannot be executed at componentWillUpdate, which will cause the render loop to be executed.

If the component is updated by the parent component update props, do so before shouldComponentUpdate componentWillRecieveProps method. This method can be used as an opportunity for React to render the setState before the props are passed. Calling setState in this method does not render the setState twice.

componentWillReceiveProps(nextProps) {
  if ('activeIndex' in nextProps) {
    this.setState({
      activeIndex: nextProps.activeIndex
    })
  }
}
Copy the code

The React with DOM

ReactDOM

There are very few apis in ReactDOM, just findDOMNode, unmountComponentAtNode, and Render. FindDOMNode Reactz provides two methods for retrieving DOM elements. One is the findDOMNode method provided by ReactDOM:

DOMElement findDOMNode(ReactComponent component)
Copy the code

After the component is rendered into the DOM, findDOMNode returns the DOM node corresponding to the React component instance. It can be used to get the value of the form as well as measurements for the DOM.

class App extends Component {
  componentDidMount() {
    const dom = ReactDOM.findDOMNode(this)
  }

  render() {}
}
Copy the code

render

ReactComponent render(
  ReactElement element,
  DOMElement container,
  [function callback])Copy the code

This method mounts the element into the Container and returns an instance of the element (that is, a refs reference). Render returns null if it is a stateless component. The callback is called when the component has been loaded.

In contrast to Render, React also provides a little-used unmountComponentAtNode method to perform the uninstall operation.

ReactDOM’s unstable approach

Unstable_renderSubtreeIntoContainer. It can update components to the incoming DOM node. It differs from the Render method in whether a parent node is passed in.

Another unstable method in ReactDOM, unstable_batchedUpdates, is related to the setState update policy.

refs

It is a very special prop in the React component that can be attached to any component. When a component is called, a new instance of that component is created, and refs points to that instance.

Neither findDOMNode nor refs can be used in stateless components, where a stateless component mount is just a method call without creating a new instance.

DOM operations outside of React

Using HTML5 Audio/Video’s play method and input’s Focus method, React doesn’t do anything. You need to use the corresponding DOM method to implement it.

There are also event bindings for areas outside the component (document, body) and DOM sizing.

reference

Inside the React Technology Stack