A simple classification of components

  • Functional components:Functional components apply toSimple componentsWe can simply assume that we only need to present the data according to the props passed inYou don't need to involve stateComponents of state operations are classified as simple components
// 1. Create functional components
function Demo() {
  console.log(this) // 这里的this是undefined
  return <h1>Components defined with functions apply to simple component definitions</h1>
}
// 2. Render the component to the page
ReactDOM.render(<Demo/>.document.getElementById('test'))
Copy the code

Since JSX is translated by Babel, functions turn on strict mode by default, so this will be undefined in functional components What happens when you call the render function to render the function component to the page?

  1. React parse component labels and find corresponding components (error if not found)
  2. Discovering that the component is defined using a function, which is then called to turn the returned virtual DOM into the real DOM and render it on the page
  • Types of components:Class components apply toComplex componentsWe can simply consider that components that need to involve complex operations such as data presentation and interaction are classified as complex components
// 1. Create class components
class Demo extends React.Component {
  render() {
    console.log(this)
    return <h1>Class components apply to the definition of complex components</h1>}}// 2. Render the class component to the page
ReactDOM.render(<Demo/>.document.getElementById('test'))
Copy the code

Class component this is the instance object of the class component What happens when you call the Render function to render the class component to the page?

  1. React parse component labels and find corresponding components (error if not found)
  2. Find the class defined on the component, then new out the instance of that class, and invoke the Render method on the prototype through that instance
  3. Turn the virtual DOM returned by the Render method into a real DOM and render it on the page

Three properties of a component

  • state

Function components do not have their own this, so they cannot access the state property. In general, function components are called stateless components. We are not talking here about the use of state as defined in the Hooks class component

// 1. Create class components
class Weather extends React.Component{
  constructor(props) {
    super(props)
    this.state = {
      isHot: false
    }
    this.changeWeather = this.changeWeather.bind(this)}changeWeather() {
    let isHot = this.state.isHot
    this.setState({
      isHot: !isHot
    })
  }
  render() {
    console.log(this);
    const {isHot}  = this.state
    return <h1 onClick={this.changeWeather}>The weather isHot today. 'Hot' : 'cool '}</h1>}}// 2. Render the component to the page
ReactDOM.render(<Weather />.document.getElementById('test'))
Copy the code
  1. State is calledstate, is a componentInternal data, we can construct methods inconstructorInInitialize theAnd then used in the corresponding JSXthis.stateAccess, and modify throughsetStateMethod is dynamically modified becauseDirect changes do not trigger Render to reproduce
  2. Notice that the callback function for the click event was performed in constructorThis points to the modificationThe callback function in the bind click event does not actually get this, so why does the render method get this? This was actually pointed out in the previous article, thisThe Render method is called on the prototype object of the class through the instance object of the classSo here’s theThis will point to an instance of the classObject, while the click event binding method is acted asThe event callback is called directly, not by instance, and strict mode is turned on by default, so this is undefined, so you need to modify this to get an instance of the class

We can omit this from development without constructor, as there are abbreviations

// 1. Create class components
class Weather extends React.Component{
  state = {
    isHot: false
  }
  changeWeather = () = > {
    let isHot = this.state.isHot
    this.setState({
      isHot: !isHot
    })
  }
  render() {
    console.log(this);
    const {isHot}  = this.state
    return <h1 onClick={this.changeWeather}>The weather isHot today. 'Hot' : 'cool '}</h1>}}// 2. Render the component to the page
ReactDOM.render(<Weather />.document.getElementById('test'))
Copy the code

Class attributes can be defined directly through assignment statements

  1. The state property is initializedCan be used directly within a classAssignment statementDefine attributes
  2. We know that the arrow function does not have its own this, but if we use this inside the arrow function, we will use this from the outer function as this in the arrow function, soCustom methodsCan pass through the classAssignment statement + arrow functionMethod to define
  • props

Prop is an attribute of the component itself. If a prop is an attribute of the component, the props can be used to access the props. In the class component, the instance object of the class is bound to the props property, so we can access the props directly. The property data will be passed as parameters, which we can access directly using the props function parameter. In addition, if there is a lot of data and you need to batch pass the data, you can use the expansion operator on the label to pass the data. Note that: In JS, the expansion operator can not operate on objects directly, but can use the literal form of objects to perform assignment deconstruction. Babel and React are needed to expand objects on labels

// Functional components
function Person(props) {
  const {name, age} = props
  return (
      <ul>
        <li>Name: {name}</li>
        <li>Age: {age}</li>
      </ul>)}/ / class components
class Person extends React.Component{
  render() {
    const {name, age} = this.props
    return (
      <ul>
        <li>Name: {name}</li>
        <li>Age: {age}</li>
      </ul>
    )
  }
}

ReactDOM.render(<Person name="tom" age="19"/>.document.getElementById('test'))
const person = {
  name: 'tom'.age: 19
}
ReactDOM.render(<Person {. person} / >.document.getElementById('test1'))
Copy the code

Limit the props passed: Prop types. Js is used to limit props, and global properties are added to propTypes. There are two properties PropTypes on the component that limit data to be passed. DefaultProps specifies the default value for passing data (case sensitive)

Person.propTypes = {
  // Restrict the name attribute type to String and must be passed
  name: PropTypes.string.isRequired
}
Person.defaultProps = {
  // If the ADDR attribute is not passed, the default value is displayed
  addr: 'the earth'
}
Copy the code

Restrictions on props in a class component can be abbreviated with the static keyword

static propTypes = {
  // Restrict the name attribute type to String and must be passed
  name: PropTypes.string.isRequired
}
static defaultProps = {
  // If the ADDR attribute is not passed, the default value is displayed
  addr: 'the earth'
}
Copy the code
  • refs

The ref attribute is used to uniquely bind the tag, and this. Refs is used to retrieve the binding node from the class component. React advises against overusing refs

  1. String binding form (It is likely to be abandoned in a way that is not efficient)
class Demo extends React.Component{
  // Click the button to display the data
  showData = () = > {
    const {input1} = this.refs
    alert(input1.value)
  }
  // Lose focus display data
  showData2 = () = > {
    const { input2 } = this.refs
    alert(input2.value)
  }
  render() {
    return (
      <div>
        <input ref="input1" type="text" placeholder="Click the button to prompt data" />  
        <button onClick={this.showData}>Am I</button>
        <input ref="input2" onBlur={this.showData2} type="text" placeholder="Lost focus prompt data"/>
      </div>
    )
  }
}

ReactDOM.render(<Demo />.document.getElementById('test1'))
Copy the code
  1. Callback function form
class Demo extends React.Component{
  // Click the button to display the data
  showData = () = > {
    const {input1} = this
    alert(input1.value)
  }
  // Lose focus display data
  showData2 = () = > {
    const { input2 } = this
    alert(input2.value)
  }
  / / save the input
  saveInput = node= > {
    this.input2 = node
  }
  render() {
    return (
      <div>{/** callback is called twice during data update **/}<input ref={node= >This. input1 = node} type="text" placeholder=" placeholder "/><button onClick={this.showData}>Am I</button>{/* Write the function as a class binding function to avoid the update call twice */}<input ref={this.saveInput} onBlur={this.showData2} type="text" placeholder="Lost focus prompt data"/>
      </div>
    )
  }
}

ReactDOM.render(<Demo />.document.getElementById('test1'))
Copy the code

The arguments in the callback function are the bound nodes. If you use the inline function binding, the callback function will fire twice when using setState to update the data. If you use the class binding, you can avoid this problem, but the official documentation states that this problem is irrelevant

  1. CreateRef form

You can call React. CreateRef to generate a container that stores nodes identified by ref (the container can store only one node and is an overridden relationship) and then access the node through the current property

class Demo extends React.Component{
  myRef = React.createRef()
  myRef2 = React.createRef()
  // Click the button to display the data
  showData = () = > {
    alert(this.myRef.current.value)
  }
  // Lose focus display data
  showData2 = () = > {
    alert(this.myRef2.current.value)
  }
  render() {
    return (
      <div>
        <input ref={this.myRef} type="text" placeholder="Click the button to prompt data" /> 
        <button onClick={this.showData}>Am I</button>
        <input ref={this.myRef2} onBlur={this.showData2} type="text" placeholder="Lost focus prompt data"/>
      </div>
    )
  }
}

ReactDOM.render(<Demo />.document.getElementById('test1'))
Copy the code

In order not to overuse ref, you can also get the DOM element object where the event occurred via event.target

class Demo extends React.Component{
  // Lose focus display data
  showData2 = (event) = > {
    alert(event.target.value)
  }
  render() {
    return (
      <div>
        <input onBlur={this.showData2} type="text" placeholder="Lost focus prompt data"/>
      </div>
    )
  }
}
ReactDOM.render(<Demo />.document.getElementById('test1'))
Copy the code

Have noticed the JSX binding way with native dom events binding way very like but it is different (case), in order to better compatibility, actually React is using a custom event (synthetic), rather than the native dom events, and in order to more efficient, the React adopted the entrusted to handle events (entrusted to the outermost element)