Study notes of React advanced guidance 4

Static type check

image Flow and TypeScript These static type inspectors can identify some types of problems before running. They can also improve the workflow of developers by adding automatic completion and other functions. For this reason, we recommend using Flow or TypeScript instead of PropTypes in large code bases. (quoted from official website)

In this section, we mainly talk about how to use Flow and TypeScript to detect static types. If the project is built through create react app, these two schemes can be used out of the box, and only simple configurations need to be added. Such as Flow:

// 1. Add Flow to the project
yarn add --dev flow-bin

// 2. In package Add in scripts in JSON
"scripts":{
    ...,
    "flow": "flow"
}

// 1. Run flow
yarn flow

The above is a simple flow configuration. As long as the page annotated with / / @ flow is used in the project, flow will detect the page and finally return whether there are exceptions. Then we will talk about the configuration of TypeScript:

TypeScript Is a programming language developed by Microsoft. It is a type superset of JavaScript and contains a separate compiler. As a type language, TypeScript can find bug s and errors during construction, so that such errors can be avoided when the program runs. (quoted from official website)

As we all know, it is necessary to define types when programming with TS, which can be verified when using. If @ reat type / APP type is already configured in the existing @ reat type / APP DOM environment, you can run @ reat type / add type in @ reat type. Then rename all JS class files, e.g. (replace src/index.js with src/index.tsx)

PS: for users who configure through webpack, Flow needs to remove its syntax during compilation, otherwise an error will be reported: see for specific configuration flow-remove-types

Strict mode

Strict mode is somewhat similar to the usage of Profiler mentioned above, but strict mode is used to detect the legitimacy of internal components through StrictMode. At present, it is mainly used for the following items:

(quoted from official website)

The so-called unsafe life cycle is mainly aimed at the exceptions that occur during the call of several life cycles used for update Asynchronous rendering update This is described. In the following references, react specifically sets UNSAFE for componentWillMount, componentWillReceiveProps and componentWillUpdate_ It can be seen that these updates are UNSAFE in react's view. In addition, in react17 After 0, a new life cycle will be added to improve the existing update mechanism: getDerivedStateFromProps and getSnapshotBeforeUpdate.

Conceptually, React works in two stages:

  • The rendering phase determines what changes need to be made, such as DOM. At this stage, React calls render and then compares the result with the last rendered result.
  • The submission phase occurs when the React application changes. (for React DOM, it occurs when React inserts, updates and deletes DOM nodes.) At this stage, React also calls lifecycle methods such as componentDidMount and componentDidUpdate.

The commit phase is usually fast, but the rendering process can be slow. Therefore, the upcoming concurrent mode (not enabled by default) breaks down the rendering work into multiple parts and pauses and resumes the task to avoid blocking the browser. This means that React can call the methods of the render phase lifecycle multiple times before committing, or call them without committing (interrupted by errors or higher priority tasks).

The lifecycle of the rendering phase includes the following class component methods:

  • constructor
  • componentWillMount (or UNSAFE_componentWillMount)
  • componentWillReceiveProps (or UNSAFE_componentWillReceiveProps)
  • componentWillUpdate (or UNSAFE_componentWillUpdate)
  • getDerivedStateFromProps
  • shouldComponentUpdate
  • render
  • setState update function (first parameter)

Because the above methods may be called many times, it is very important not to write code related to side effects inside them. Ignoring this rule can lead to various problems, including memory leaks and or invalid application states. Unfortunately, these problems are difficult to detect because they usually have Uncertainty.

Strict mode can't automatically detect your side effects, but it can help you find them and make them more deterministic. This operation is achieved by deliberately repeatedly calling the following functions:

  • constructor, render and shouldComponentUpdate methods of class component
  • class component's lifecycle method getDerivedStateFromProps
  • Function component body
  • State update function (i.e. the first parameter of setState)
  • Function components use useState, useMemo or useReducer

(the above is quoted from the official website)

Use PropTypes type check

This module is about how PropTypes are used in react and how most decision functions are written. Because there are too many types, I won't copy and paste them. If you want to know later, just go to the official website and see for yourself. The title above is a direct link.

Uncontrolled components

For a component that accepts parameters and returns corresponding results, it is divided into uncontrolled components and controlled components, and its parameters are also divided into controlled parameters and uncontrolled parameters. With antd4 0 as an example, the parameter defaultValue is basically uncontrolled, while value is controlled. You can control the internal function rendering in the outer layer, and the changes in the outer layer will be transferred to the interior for modification.
Generally speaking, whether to use setState or ref to obtain data is mainly determined according to the current needs. If you don't need dynamic updates, it's convenient to use ref, and vice versa. Below is a Form that feels like a fake uncontrolled component, a Form that emulates antd, using several methods learned in the advanced guidelines and react Children:

/**
 * @desc Page for testing notcontract
 * @name NotContral
 * @author Cyearn
 * @date 2020/11/21
 */

import React, { Component } from "react";
import styles from "./styles.module.less";

class NotContral extends Component {
  constructor(props) {
    super(props);
    this.state = {};
    this.ref = React.createRef();
  }
  componentDidMount() {}
  submit = () => {
    const { setValue, getValue } = this.ref;
    console.log(getValue());
  };
  render() {
    return (
      <div className={styles.contain}>
        <Form refForm={(el) => (this.ref = el)}>
          <Item label={"account number"} name={"username"}>
            <Input />
          </Item>
          <Item label={"password"} name={"password"}>
            <Input />
          </Item>
        </Form>
        <button onClick={this.submit}>Submit</button>
      </div>
    );
  }
}
const Form = function (props) {
  const { children, refForm } = props;

  const ReForm = withForm(children, refForm);
  return (
    <div>
      test
      <ReForm ref={refForm} />
    </div>
  );
};

function withForm(children, refForm) {
  if (children) {
    return class extends Component {
      constructor(props) {
        super(props);
        this.state = {};
      }

      componentDidMount() {
        let param = {};
        // Inject default values into subcomponents and the onChange event
        this.Children = React.Children.map(children, (child) => {
          param[child.props.name] = "";
          let key = child.props.name;
          return React.cloneElement(child, {
            onChange: this.changeInput,
            defaultValue: this.state[key],
            value: this.state[key],
          }); //This time we passed react Adding properties to cloneelement
        });
        this.setState({
          ...param,
        });
      }
      // Define set value function
      setValue = (obj = {}) => {
        this.setState({
          ...obj,
        });
      };
      // Define get value function
      getValue = () => {
        const all = this.state;
        return { ...all };
      };
      // A function that changes data in a form
      changeInput = (e, id) => {
        let param = {};
        param[id] = e;
        this.setState({
          ...param,
        });
      };

      onValueChange = () => {};

      render() {
        return <form onValueChange={this.onValueChange}>{this.Children}</form>;
      }
    };
  }
}

// HOC
function WithItem(Inject, props) {
  class Test extends Component {
    constructor(props) {
      super(props);
      this.state = { value: "" };
    }
    render() {
      const { value } = props;
      console.log(value);
      return (
        <Inject
          {...props}
          onChange={(e) => props.onChange(e, props.name)}
          value={value}
        />
      );
    }
  }
  return Test;
}

// Wrap child node
class Item extends Component {
  constructor(props) {
    super(props);
    this.state = {};
  }
  render() {
    const { label, children, ...other } = this.props;
    let type = children && children.type;
    if (type) {
      const Children = WithItem(this.props.children.type, { ...other });
      return (
        <section style={{ marginBottom: 10 }}>
          <span>{label}:</span>
          <Children />
        </section>
      );
    } else {
      return null;
    }
  }
}

// Minimum node
function Input(props) {
  const { onChange, value } = props;
  return (
    <input
      type="text"
      onChange={(e) => onChange(e.target.value)}
      value={value}
    />
  );
}

export default NotContral;

Tags: Javascript ECMAScript React

Posted by u01jmg3 on Fri, 06 May 2022 00:55:49 +0300