preface

To go fast, the screws have to be tightened. Said is me this kind of pheasant, only to run forward, remember to wear shoes. Run to the end, the referee said you did not wear shoes, the result does not count, the result is close

Today I’m going to unscrew three important screws

During React development, the three most common attributes are state, PORps, and REF

Because of volume reasons, I use React +vite+TypeScript to create a project to review the three properties. On the one hand, it can deepen the application of TS, on the other hand, it can deepen the understanding of React.

Three properties of a component instance – state

Definition: This is equivalent to an object that stores data.

If you have used vUE, you know that the data stored in the current instance in VUE is data, and this data is officially recommended as a function rather than an object, you can check it out. The reason for personal summary is that each. Vue is a single instance, and if you use objects, this will become global. Can affect the data of other instances, and the scoped function does not affect.

Writing a:

import React, { Component } from "react";

interface stateType {
  isHot: boolean;
  wind: string;
}

export default class App extends Component<{}, stateType> {
  constructor(props: any) {
    super(props);
    // Initialization state
    this.state = { isHot: false.wind: "The wind" };
    this.changeWeather = this.changeWeather.bind(this);
  }
  changeWeather() {
    console.log("changeWeather".this);
    // Get the old isHot value
    const isHot = this.state.isHot;
    this.setState({ isHot: !isHot });
  }
  render() {
    console.log("render");
    const { isHot, wind } = this.state;
    return (
      <h1 onClick={this.changeWeather}>The weather isHot today. }, {wind}</h1>); }}Copy the code

So there’s a couple of things that I want to sort through,

Component<{}, stateType>

If those of you familiar with TS know that this is a type assertion, and stateType is a custom interface, why are there two parameters in it? Let’s look at the Component defined in the React source code

Component

, where P and S are generic. State is defined as Readonly
, meaning that all properties of state are read-only. Props are defined as Readonly < P > | P, means: all props attribute is set to read-only type Or the P type

,s>

Component<{}, stateType> Component<{}, stateType>

ChangeWeather = this.changeweather.bind (this); changeweather.bind (this);

As those of you who have written ES6 classes know, methods defined in the class class are provided to the App prototype object for instance use before they are modified by property modifiers.

ES6 class modifiers (see Teacher Ruan Yifeng’s ES6 explanation for details) :

  • Static properties and static methods are added earlierstatic .
  • Private attributes are added earlier#
  • Private methods are underlined, but can also be accessed externally

TS class modifiers: TS class modifiers

  • publicModifier – Public, the default modifier for a member of a class. It represents public, accessible from anywhere in the class
  • privateModifiers – private. Members of a class that use private modifiers cannot be accessed externally or by subclasses
  • protectedModifiers – Protected members of a class cannot be accessed by outsiders, although subclasses can
  • #Modifiers – represent private fields, sometimes called private names; Each private field name is uniquely qualified to the class it contains; You cannot use TypeScript accessibility modifiers (such as public or private) on private fields; Private fields cannot be accessed outside of the contained class or even detected
  • readonlyModifier – read-only cannot write
  • staticModifier — passstaticThe modified member is calledStatic membersStatic members are called directly by class name without instantiation

Because changeWeather is called as a callback to onClick, it is not called by instance, but directly. The method in the class has local strict mode enabled by default, so this in changeWeather is undefined.

    function aa(){
        console.log(this)
    }
    aa()

    function bb(){
        "use strict";
        console.log(this)
    }

    bb()
Copy the code

Printed results:

If you are familiar with “This”, you will know the reason. I will also summarize it for you. I will not introduce it in detail here.

  • In strict mode, this refers to the window object in the global scope.
  • In strict mode, this in a function in the global scope equals undefined. When not in strict mode, this refers to the window. In React render(), this is the instance object that points to the component. Note the distinction between this in render() and this in the function. (The “this” and “this” refer to different things, so you can’t call this directly from globally-scoped functions.)
  • In strict mode, the this in an object’s function refers to the instance of the object calling the function
  • In strict mode, this in the constructor refers to the object instance created by the constructor.
  • In strict mode, in event handlers, this points to the target object that triggered the event.

So finally, do you know why you changed the “this” in changeWeather?

So with all of this, let’s write it in shorthand

Method 2:

import React, { Component } from "react";
interface stateType {
  isHot: boolean;
  wind: string;
}

export default class example1 extends Component<{}, stateType> {
  state = {
    isHot: false.wind: "The wind"}; changeWeather =() = > {
    const isHot = this.state.isHot;
    this.setState({ isHot: !isHot });
  };

  render() {
    const { isHot, wind } = this.state;
    return (
      <h1 onClick={this.changeWeather}>The weather isHot today. }, {wind}</h1>); }}Copy the code

I don’t know if this is going to be much simpler than one.

ChangeWeather = ‘this’; changeWeather =’ this’;

Arrow functions do not create their own this. Deep understanding!!) That is to say, it does not have its own this. If you are interested, take a look at MDN’s interpretation of this for arrow functions

The arrow function inherits this pointer forever. Deep understanding!!)

.call()/.apply()/.bind() cannot change the direction of this in the arrow function

Arrow functions cannot be used as constructors, that is, they cannot be new. What does the constructor new do first? In short, there are four steps:

① JS will first be an object inside;

② Add this to the object;

③ Execute the statement in the constructor;

④ The object instance is returned.

But!!!!! Arrow functions cannot be used as constructors, or constructors cannot be defined as arrow functions, because the arrow function does not have its own this, and its this inherits from the outer execution environment, and this never changes depending on where or by whom it is called.

let Fun = (name, age) = > {
    this.name = name;
    this.age = age;
};

/ / an error
let p = new Fun('cao'.24);
Copy the code

Arrow functions have no arguments of their own. Calling Arguments in the arrow function actually gets the value in the outer local (function) execution environment.

A / / examples
let fun = (val) = > {
    console.log(val);   / / 111
    // The following line is an error
    // Uncaught ReferenceError: arguments is not defined
    // There are no arguments objects in the outer global environment
    console.log(arguments); 
};
fun(111);

2 / / examples
function outer(val1, val2) {
    let argOut = arguments;
    console.log(argOut);    / / 1.
    let fun = () = > {
        let argIn = arguments;
        console.log(argIn);     / / 2.
        console.log(argOut === argIn);  / / 3.
    };
    fun();
}
outer(111.222);
Copy the code

In example 2, ①, ②, ③, the output is as follows:

Obviously, ordinary functionsouterThe inner arrow functionfunIn theargumentsObject, which is actually an outer layer accessed up the scope chainouterFunction of theargumentsObject.

You can use rest arguments in arrow functions instead of arguments objects to access the argument list of arrow functions!!

Arrow function has no prototype

Arrow functions cannot be used as Generator functions. The yeild keyword cannot be used

A single state allows me to learn about class modifiers, this Pointers, arrow functions, generics, type assertions, generics tools, and union types. I’m afraid I’ve covered so much.

Three properties of a component instance – props

Definition: bridge function when a parent component passes parameters to a child component, equivalent to the function when a vue props passes values, but not as cumbersome as vue.

Writing:

import React, { Component } from "react";
interface propsType {
  name: string;
  age: number;
  sex: "Male" | "Female";
}

class Index1 extends Component<propsType> {
  render(): React.ReactNode {
    const { name, age, sex } = this.props;
    return (
      <ul>
        <li>Name: {name}</li>
        <li>Gender: {sex}</li>
        <li>Age: {age}</li>
      </ul>); }}export default class example2 extends Component {
  render() {
    let p:propsType = {
      name:"Li Qingxia".age:20.sex:"Female"
    }
    return (
      <>
        <h1>Basic use of Props</h1>
        <Index1 name="Week star" age={18} sex="Male"></Index1>
        <Index1 name="Athena chu" age={19} sex="Female"></Index1>
        <Index1 {. p} ></Index1>
      </>); }}Copy the code

React props is a function that can be used to write functions in the same way as vue.

When we use prop in VUE, there will be a type definition, whether it is required to pass, and can also write verification rules

React also supports PropsType, but uses another library called prop-types. See PropsType for details.

import React, { Component } from "react";
import PropTypes from "prop-types";
interface propsType {
  name: string;
  age: number;
  sex: "Male" | "Female"; speak? :Function
}
function speak() {
  console.log("I spoke.");
}

class Index1 extends Component<propsType> {
  static propTypes: { name: PropTypes.Validator<string>; sex: PropTypes.Requireable<string>; age: PropTypes.Requireable<number>; speak: PropTypes.Requireable<(. args:any[]) = > any>};static defaultProps: {
    sex: string; //sex The default value is male
    age: number; //age The default value is 18
    name: string;
  };
  render(): React.ReactNode {
    const { name, age, sex,speak } = this.props;
    if(speak){ speak! (a)console.log("Who's talking?",name)
    }
    
    return (
      <ul>
        <li>Name: {name}</li>
        <li>Gender: {sex}</li>
        <li>Age: {age}</li>
      </ul>
    );
  }
}
Index1.propTypes = {
  name: PropTypes.string.isRequired,
  sex: PropTypes.string,
  age: PropTypes.number,
  speak: PropTypes.func,
};

Index1.defaultProps = {
  sex: "Male".//sex The default value is male
  age: 18.//age The default value is 18
  name: "Bill"};export default class example2 extends Component {
  render() {
    let p: propsType = {
      name: "Li Qingxia".age: 20.sex: "Female"};return (
      <>
        <h1>Basic use of Props</h1>
        <Index1 name="Week star" age={18} sex="Male" speak={speak}></Index1>
        <Index1 name="Athena chu" age={19} sex="Female"></Index1>
        <Index1 {. p} ></Index1>
        <Index1></Index1>
      </>); }}Copy the code

In a strongly typed language like TS, it is possible to define the interface type in advance.

And then we can abbreviate it:

import React, { Component } from "react";
import PropTypes from "prop-types";
interface propsType {
  name: string;
  age: number;
  sex: "Male" | "Female";
}
function speak() {
  console.log("I spoke.");
}

class Index1 extends Component<propsType> {
  static propTypes: { name: PropTypes.Validator<string>; sex: PropTypes.Requireable<string>; age: PropTypes.Requireable<number>; speak: PropTypes.Requireable<(. args:any[]) = > any>} = {name: PropTypes.string.isRequired,
    sex: PropTypes.string,
    age: PropTypes.number,
    speak: PropTypes.func,
  };
  static defaultProps: {
    sex: string; //sex The default value is male
    age: number; //age The default value is 18
  } = {
    sex: "Male".//sex The default value is male
    age: 18.//age The default value is 18
  };
  render(): React.ReactNode {
    const { name, age, sex } = this.props;
    return (
      <ul>
        <li>Name: {name}</li>
        <li>Gender: {sex}</li>
        <li>Age: {age}</li>
      </ul>); }}export default class example2 extends Component {
  render() {
    let p: propsType = {
      name: "Li Qingxia".age: 20.sex: "Female"};return (
      <>
        <h1>Basic use of Props</h1>
        <Index1 name="Week star" age={18} sex="Male"></Index1>
        <Index1 name="Athena chu" age={19} sex="Female"></Index1>
        <Index1 {. p} ></Index1>
        <Index1 name="Bill"></Index1>
      </>); }}Copy the code

Functional components are written similarly:

import PropTypes from "prop-types";
import React from "react";
interface propsType {
  name: string;
  age: number;
  sex: "Male" | "Female";
}
function Index1(props: propsType) {
  const { name, age, sex } = props;
  return (
    <ul>
      <li>Name: {name}</li>
      <li>Gender: {sex}</li>
      <li>Age: {age}</li>
    </ul>
  );
}

Index1.propTypes = {
  name: PropTypes.string.isRequired, // Restrict name to a string
  sex: PropTypes.string, // Restrict sex to a string
  age: PropTypes.number, // Limit age to a numeric value
};

// Specify the default tag attribute value
Index1.defaultProps = {
  sex: "Male".//sex The default value is male
  age: 18.//age The default value is 18
};

export default function example5() {
  return (
    <>
      <h1>The function component uses props</h1>
      <Index1 name="Bill"></Index1>
    </>
  );
}
Copy the code

Three properties of a component instance – ref

Definition: Usually used to retrieve DOM or DOM values, such as the input tag, which can be bound to the input value

Ref as a string

import React, { Component } from "react";

export default class example6 extends Component {
  showData = () = >{
    / / complains
    console.log(this.refs)
  }
  render() {
    return (
      <>
        <h1>Ref as a string</h1>
        <input ref="inputRef" type="text"  placeholder="Please enter"/>
        <button onClick={this.showData}>Get ref</button>
      </>); }}Copy the code

React: Ref (Ref) : Ref (Ref) : Ref (Ref

A callback function in the form of ref

import React, { Component } from "react";

export default class example6 extends Component {
  showData = () = > {
    const { inputRef } = this;
    console.log(inputRef? .value); }; inputRef: HTMLInputElement |null | undefined;
  render() {
    return (
      <>
        <h1>A callback function in the form of ref</h1>
        <input ref={(c)= >(this.inputRef = c; console.log('@',c);) Placeholder =" placeholder "; placeholder=" placeholder ";<button onClick={this.showData}>Get ref data</button>
      </>); }}Copy the code

This will not give an error, but there is a problem, when I render update, the callback will always be called.

To solve this problem, write:

import React, { Component } from "react";

export default class example6 extends Component {
  state = { isHot: false };

  showInfo = () = > {
    const { inputRef } = this; alert(inputRef! .value); }; changeWeather =() = > {
    // Get the original state
    const { isHot } = this.state;
    // Update the status
    this.setState({ isHot: !isHot });
  };

  saveInput = (c: HTMLInputElement | null | undefined) = > {
    this.inputRef = c;
    console.log("@", c);
  };
  inputRef: HTMLInputElement | null | undefined;
  render() {
    const { isHot } = this.state;
    return (
      <>
        <h2>The weather isHot today. "Hot" : "cool "}</h2>
        <input ref={this.saveInput} type="text" />
        <br />
        <br />
        <button onClick={this.showInfo}>Click on the data I prompted for input</button>
        <button onClick={this.changeWeather}>Click on me to switch the weather</button>
      </>); }}Copy the code

CreateRef create ref

This method is much easier to use than the above ones, personally

import React, { Component } from "react";

export default class example9 extends Component {
  myRef = React.createRef<HTMLInputElement>();
  myRef2 = React.createRef<HTMLInputElement>();
  // Display the data in the left input box
  showData = () = > {
    alert(this.myRef.current! .value); };// Display the data in the input box on the right
  showData2 = () = > {
    alert(this.myRef2.current! .value); };render() {
    return (
      <div>
        <input ref={this.myRef} type="text" placeholder="Click the button to prompt data" />
        &nbsp;
        <button onClick={this.showData}>Click on the data to the left of my tip</button>&nbsp;
        <input onBlur={this.showData2} ref={this.myRef2} type="text" placeholder="Lost focus prompt data" />
        &nbsp;
      </div>); }}Copy the code

conclusion

I have unscrewed the state, props, and ref screws in React. I also unscrewed the class modifier, this pointer, arrow functions, generics, type assertions, generics tools, and union types. Ready to go. You guys are ready

Today specially set up a reminder, remind today is Thursday to post learning to share