I met

React is an open source JavaScript library that renders data into HTML views

The advantages of the React

  1. Componentized mode and declarative coding are adopted to improve development efficiency and component reuse rate
  2. React Native allows you to use the React syntax for mobile applications.
  3. Use virtual DOM + excellent Diffing algorithm to minimize interaction with real DOM and minimize page redrawing

Hello React

Babel.js is used to convert JS to JSX. UMD versions of React and ReactDOM are available via CDN.

The import order is to introduce the core library dom Babel

<! -- What a container -->
<div id="test"></div>

<! -- Introducing a core library -->
<script src=".. /react.development.js"></script>
<! React-dom is used to support the react operation.
<script src=".. /react-dom.development.js"></script>
<script src=".. /babel.min.js"></script>
<script type="text/babel"> // This must be written as Babel
  // Create virtual DOM
  const Virtual = (  // Do not use quotation marks here because this is the virtual DOM
    <h1>hello,react</h1>
  )
  // Render the virtual DOM to the page
  // reactdom.render (virtual DOM, container)
  // reactdom.render (Virtual,"#test") //React does not provide such a syntax
  ReactDOM.render(Virtual,document.getElementById('test'));
</script>
Copy the code

Js is different from JSX

Use JS to create the virtual DOMconst VDOM = React.createElement("h1, {id:"title"}, React.createElement("span")); Const Virtual = (

title"> )Copy the code

Virtual DOM annotation

  const Virtual = ( 
    <h1>
		{ /* <span id="title"></span>*/ * * * * * * * * * * * * * * * *</h1>
  )


  const Virtual = ( 
    <h1>
		<span id="title"></span>
    </h1>Virtual DOM is an object debuger test. Virtual DOM is an object debuger testCopy the code

JSX syntax rules javascript XML

Const VDOM = react. createElement(“h1, {id:”title”}, react. createElement(“span”));

{} —– what is an expression? What is a statement?

  const myId = 'aTguiGu'
  const myData = 'hello,ReaCt'
  const Virtual = (
    <h1 id={myId.toLocaleLowerCase()}>// Tags are mixed with js expressions using {}<span>{myData.toLocaleLowerCase()}</span>  
    </h1>
  )
  ReactDOM.render(Virtual,document.getElementById('test')); Expression a a+b demo(1)
  arr.map()
  function(){}
  
  consti = ? An expression statement is one that connects valuesif() {}for() {}switch() {}constI = No value is connectedCopy the code

The JSX style class is called className because it conflicts with the JS class


  const Virtual = (  // Do not use quotation marks here because this is the virtual DOM
    <h1 className="title" id={myId.toLocaleLowerCase()}>
      <span>{myData.toLocaleLowerCase()}</span>  
    </h1>
  )
Copy the code

Sytle ={{key:value,key:value}}

  const Virtual = (  // Do not use quotation marks here because this is the virtual DOM
    <h1 className="title" id={myId.toLocaleLowerCase()}>
      <span style={{color:'red',fontSize:'50px'}} >{myData.toLocaleLowerCase()}</span>  
    </h1>
  )
Copy the code

There can be only one root tag. The tag must be closed

Label first letter

If it starts with a lowercase letter, the tag is converted to an element of the same name in HTML. If there is no corresponding element in HTML, an error is reported

If it starts with an uppercase letter, find the corresponding component directly

React will automatically iterate over arrays of values

React will automatically iterate through groups for you

  const data = ['Angular'.'React'.'Vue']
  const Virtual = (
    <div>
      <h1>The front frame</h1>
      <ul>{data.map((item,index)=>{// Only return<li key={index}>{item}</li>})}</ul>  
    </div>
  )
  ReactDOM.render(Virtual,document.getElementById('test'));
Copy the code

Component-oriented programming

Install react Dev Tools

The console allows you to view components and test tools

Methods for defining components

Functional component

The function must have a return value hanging on the must be end tag

  // Create functional components
  function MyComponent() {
    return <h2>I am a function defined component (for simple component definitions)</h2>  // There must be a return value
  }
  					// Must be the end tag
  ReactDOM.render(<MyComponent/>.document.getElementById('test'));
Copy the code

Use of the class class

// Create a Person class
class Parson{
  / / the constructor
  constructor(name,age){
    this.name = name
    this.age = age
  }
  // General method
  speak(){
    // Speak on the chain
    console.log(I call `The ${this.name}This year, IThe ${this.age}At the age of `); }}// Create a student class that inherits parson
class Student extends Parson{
  // No constructor is moved directly to the inherited constructor
}

const s1 = new Student("Zhang".12)
console.log(s1);
Copy the code

Use the constructor if there are new attributes after inheritance

// Create a Person class
class Parson{
  / / the constructor
  constructor(name,age){
    this.name = name
    this.age = age
  }
  // General method
  speak(){
    // Speak on the chain
    console.log(I call `The ${this.name}This year, IThe ${this.age}At the age of `); }}// Create a student class that inherits parson
class Student extends Parson{
  constructor(name,age,grade){
    super(name,age)   // Super can only be written on the first line
    this.grade = grade
  }
}

const s1 = new Student("Zhang".12."Higher")  // One grade more than Parson
console.log(s1);
Copy the code

The constructors in the class are not required to be written or the methods in the class are placed on the prototype object

The component class type

Classes must inherit React built-in classes must have render methods render must return values



  // Create a class component
  class MyComponent extends React.Component{  // Must inherit
    render(){  / / render method
      return <h2>I am a class-defined component (for definition of a complex component)</h2>  / / the return value}}// Render the component to the page
  ReactDOM.render(<MyComponent/>.document.getElementById('test'))
  
  /* The render function in class MyComponent is used by instances but does not have a new instance. React automatically creates a new instance and calls the render method */
  
  
  
  // Create a class component
  class MyComponent extends React.Component{
    render(){
      // render where? -- On the prototype object of MyComponent for instance use
      // Who is this in rander? --MyComponent instance object or component instance object
      console.log(this);
      return <h2>I am a class-defined component (for definition of a complex component)</h2>}}// Render the component to the page
  ReactDOM.render(<MyComponent/>.document.getElementById('test'))
Copy the code

$state- The core property of the component instance – understanding state

Functional component = Simple component = No state Class component = Complex component = State

Fix this pointing problem in changeWeather

class Weather extends React.Component{
  constructor(props){
    super(props)
    // Initialization state
    this.state = {isHot:true}}render(){
    // Read the state
    const {isHot} = this.state
    		// We must write this.changeWeather because we can't get it directly
    return <h1 onClick={this.changeWeather.bind(this)}>The weather is {isHot? Hot ":" cold "}</h1>
  }
  changeWeather(){
  	// This points to undefined if you don't say bind
    console.log(this.state);
  }
}
ReactDOM.render(<Weather/>.document.getElementById("test"))
Copy the code

Or this in the following constructor is the instance object

class Weather extends React.Component{
  constructor(props){
    super(props)
    // Initialization state
    this.state = {isHot:true}
    this.changeWeather = this.changeWeather.bind(this) // This is the instance object in the constructor, and the output from this is its own changeWeather
  }
  render(){
    // Read the state
    const {isHot} = this.state
    return <h1 onClick={this.changeWeather}>The weather is {isHot? Hot ":" cold "}</h1>
  }
  changeWeather(){
    console.log(this.state);
  }
}
ReactDOM.render(<Weather/>.document.getElementById("test"))
Copy the code

The use of setState is similar to that of applets

I solved the pointing problem above and now I’m going to click on the transform true and false

class Weather extends React.Component{
  constructor(props){
    super(props)
    // Initialization state
    this.state = {isHot:true}
    this.changeWeather = this.changeWeather.bind(this)}render(){
    // Read the state
    const {isHot} = this.state
    return <h1 onClick={this.changeWeather}>The weather is {isHot? Hot ":" cold "}</h1>
  }
  changeWeather(){
  	// This is true, but the page will not be hot and cold constantly switching
    this.state.isHot = !this.state.isHot
    console.log(this.state.isHot);
  }
}
ReactDOM.render(<Weather/>.document.getElementById("test"))
Copy the code

Since things in the state cannot be changed directly, finding that property and changing it directly is a direct change


class Weather extends React.Component{
  constructor(props){
    super(props)
    // Initialization state
    this.state = {isHot:true}
    this.changeWeather = this.changeWeather.bind(this)}render(){
    // Read the state
    const {isHot} = this.state
    return <h1 onClick={this.changeWeather}>The weather is {isHot? Hot ":" cold "}</h1>
  }
  changeWeather(){
    // Seriously note that the state state cannot be changed directly
    // this.state.isHot = ! This.state. isHot // Error
    // console.log(this.state.isHot);

    ChangeWeather = this.changeweather.bind (this)
    // This is an instance of Weather
    // The prototype of the instance object has render on it. The prototype of the changeWeather object is React.Com. Ponent has a method called setState
    this.setState({
      isHot:!this.state.isHot
    })
  }
}
ReactDOM.render(<Weather/>.document.getElementById("test"))
Copy the code

A small summary of the overall structure

A small summary

class Weather extends React.Component{
  constructor(props){   // when the generated instance is called only once
    super(props)
  }
  render(){} //1+n times to return the component and then to rerender when the event function first triggers the modification state
  changeWeather(){} // Trigger several times execute several times
}
ReactDOM.render(<Weather/>.document.getElementById("test"))





class Weather extends React.Component{
  constructor(props){  // Why is the constructor written?
    super(props)
    // The state must be initialized
    this.state = {
      isHot:true.wind:"The wind"
    }
    // Solve this pointing problem
    this.changeWeather = this.changeWeather.bind(this)}render(){ // Render this is the component instance object
    // Read the state
    const {isHot,wind} = this.state
    / / do show
    return <h1 onClick={this.changeWeather}>The weather is {isHot? Hot ":" cold "}</h1>
  }
  changeWeather(){
    this.setState({
      isHot:!this.state.isHot // Get value update value
    })
  }
}
ReactDOM.render(<Weather/>.document.getElementById("test"))
Copy the code

To streamline the state

class Weather extends React.Component{
  constructor(props){}  // This must refer to the instance object
  render(){}		// React new calls render automatically, so this is also an instance object
  changeWeather(){} // This is undefined internal automatic strict mode
}

constructorThere are only two things in therethisYou can write an assignment directly to the initialization state class but it must be deadclass Weather extends React.Component{
  constructor(props){}
  render(){}
  changeWeather(){}
  a = 1
}
newThe instance that comes out will have a= 01The property of is equivalent to that ofconstructorWrite the insidethis.a= 1, so it's straight downstate
class Weather extends React.Component{
  constructor(props){}
  state = {name:"xxx"}
  render(){}
  changeWeather(){}}Copy the code

Simplified Constructord’s this points to the problem

class Weather extends React.Component{
  constructor(props){}
  render(){}
  changeWeather = function(){} A =1
  // This method is used on the prototype so that it can be directly applied to the instance properties
  // It's still not enough to just write it like this
}


class Weather extends React.Component{
  constructor(props){}
  render(){}
  // The arrow will take the external this
  log(this)?? // You can't write a function body inside a class, so don't worry about it
  changeWeather = () = >{
  	console.log(this) // is an instance object of weather}}Copy the code

The final structure pays attention to key points

class Weather extends React.Component{
  // Initialization state
  state = {
    isHot:true.wind:"Cold"
  }
  
  render(){
    const {isHot,wind} = this.state
    return <h1 onClick={this.changeWeather}>The weather is {isHot? },{wind}</h1>
  }
  
  // Custom methods -- assignment statement + arrow function
  changeWeather = () = >{
    this.setState({
      isHot:!this.state.isHot
    })
  }
}
ReactDOM.render(<Weather/>.document.getElementById("test"))
Copy the code

Pay attention to the point

  1. Render’s this is the component instance object (react automatically new and calls).
  2. Component custom methods in which this is undefined (because the class is automatically in strict mode) and the event is called without this a. Force binding this through bind() (bind, unlike call, does not perform) b. Through the arrow function
  3. The state data cannot be changed directly. You must use setState in the React prototype

$props- The core property of the component instance – props

The basic use of simple values

// Create a component
class Parson extends React.Component{
  state = { name:'tom'.age:18.sex:'woman' }
  render(){
    const {name,age,sex} = this.state
    return (
      <ul>
        <li>Name: {name}</li>
        <li>Gender: {age}</li>
        <li>Age: {sex}</li>
      </ul>
    )
  }
}
ReactDOM.render(<Parson/>.document.getElementById('app1'))
ReactDOM.render(<Parson/>.document.getElementById('app2'))
ReactDOM.render(<Parson/>.document.getElementById('app3'))
Copy the code

This is the basic notation, but now I need external data to render the above notation as if it were my own thing and render three people with the same name, gender and age

// Create a component
class Parson extends React.Component{
  render(){
    console.log(this);
    const {name,age,sex} = this.props
    return (
      <ul>
        <li>Name: {name}</li>
        <li>Gender: {age}</li>
        <li>Age: {sex}</li>
      </ul>
    )
  }
}
ReactDOM.render(<Parson name='tom' age='18' sex='woman' />.document.getElementById('app1'))
			// React automatically passes name: Tom to props
Copy the code

Batch pass props for example have a lot of information

Transferring label attributes in batches

    // Create a component
    class Parson extends React.Component {
      render() {
        console.log(this);
        const { name, age, sex } = this.props
        return (
          <ul>
            <li>Name: {name}</li>
            <li>Gender: {age}</li>
            <li>Age: {sex}</li>
          </ul>)}}const result = { name: "Liu".age: 18.sex: "Female" }
    ReactDOM.render(<Parson name={result.name} age={result.age} sex={result.sex} />.document.getElementById('app1'))
    //nonono cannot write this if there is too much data
    					/ / writes
    ReactDOM.render(<Parson {. result} / >.document.getElementById('app2') Test...var a = {n: 1.b: 2.c: "Hello"}
var b = {say:"hello"}
varobj = {... b,... A} orvar obj = new Object({... b,... A}) obj = {say: "hello".n: 1.b: 2.c: "Hello"}
Copy the code

Limit propTypes for props

Restrictions must be written to the class, not the instance

    // Create a component
    class Parson extends React.Component {
      render() {
        console.log(this);
        const { name, age, sex } = this.props
        return (
          <ul>
            <li>Name: {name}</li>
            <li>Gender: {age}</li>
            <li>Age: {sex}</li>
          </ul>)}}React every time new asks Parson if it has this thing
    Parson.propTypes = {
      // Start with a capital P, which is a built-in property of React
      name:React.propTypes.string  // The type is also lowercase
    }
    const result = { name: "Liu".age: 18.sex: "Female" }
    ReactDOM.render(<Parson name={result.name} age={result.age} sex={result.sex} />.document.getElementById('app1'))
    ReactDOM.render(<Parson {. result} / >.document.getElementById('app2'))
    
Copy the code

Limit rules

    Parson.propTypes = {
      // Start with a capital P, which is a built-in property of React
      name:React.propTypes.string  // The type is also lowercase} But this is written in16.Xx after being abandoned Because the react with propTypes will change a lot And sometimes also don't have to restrict16.The PropTypes object is added directly to the class by loading prop-types.js to restrict component tags. PropTypes writeReact every time new asks Parson if it has this thing
    Parson.propTypes = {
      // Start with a capital P, which is a built-in property of React
      name:PropTypes.string.isRequired,  // The type is also lowercase and must be entered
      sex:propTypes.string,
    }
Copy the code

The default value

    // Specify a default value
    Parson.defaultProps = {
      sex:"No, male, female.".age:18
    }
    
    

Copy the code

If the method is worn, the restriction is Handel: proptypes.func

    // Create a component
    class Parson extends React.Component {
      render() {
        const { name, age, sex,handel } = this.props
        return (
          <ul>
            <li>Name: {name}</li>
            <li>Gender: {age}</li>
            <li>Age: {sex}</li>
          </ul>)}}React every time new asks Parson if it has this thing
    Parson.propTypes = {
      // Start with a capital P, which is a built-in property of React
      name:PropTypes.string.isRequired,  // The type is also lowercase and must be entered
      sex:PropTypes.string,
      age:PropTypes.number,
      handel:PropTypes.func / / method
    }
    // Specify a default value
    Parson.defaultProps = {
      sex:"No, male, female.".age:18,}function handle(){}
    const result = { name: "Liu".sex:"Male".age: 18.handle:handle}
    ReactDOM.render(<Parson {. result} / >.document.getElementById('app2'))
Copy the code

The abbreviation for propType props is read-only and cannot be changed

Props is read-only. This. Props is equal to XXX

      render() {
        const { name, age, sex,handel } = this.props
        this.prop.xxx = xxx / / an error
        return (
          <ul>
            <li>Name: {name}</li>
            <li>Gender: {age}</li>
            <li>Age: {sex}</li>
          </ul>)}Copy the code

shorthand

    class Parson extends React.Component {
      render() {
        const { name } = this.props
        return (
          <ul>
            <li>Name: {name}</li>
            <li>Gender: {age}</li>
            <li>Age: {sex}</li>
          </ul>)}static propTypes = { // The class must be static. // The class must be static
        name: PropTypes.string.isRequired
      }
      static defaultProps = {
        sex: "No, male, female."
      }
    }
    
    Parson.propType = {  // If you want to write this directly, add static
        name: PropTypes. String. IsRequired,} class is equivalent to the prototype of instance, all the methods defined in the class, are examples of inheritance. If you have a method, plusstaticKeyword, indicating that the method is not inherited by the instance, but is called directly from the class, which is called a "static method."class Foo {
  static say() {
    return 'hello';
  }
}
Foo.say() // 'hello'

var foo = new Foo();
foo.say() // TypeError: foo.classMethod is not a functionNote that if static methods containthisKeyword, thisthisClass, not instance.Copy the code

Constructors and props in class components

Before the React component is mounted, its constructor is called. When implementing a constructor for a react.componentsubclass, it should be called before any other statementsuper(props). Otherwise,thisThere may be undefined bugs in the.props constructor.constructor(props){
        super(a)// If you don't pass it here
        console.log(props);
        console.log(this.props); // Then you can get undefined directly
      }
Copy the code

Props for functional components

Functions can have props state because they can take parameters

    function Parson(props) {
      const { name, sex, age, } = props
      return (
        <ul>
          <li>Name: {name}</li>
          <li>Gender: {age}</li>
          <li>Age: {sex}</li>
        </ul>
      )
    }
    Parson.propTypes = {
      name: PropTypes.string.isRequired,
      sex: PropTypes.string,
      age: PropTypes.number,
      handel: PropTypes.func
    }
    Parson.defaultProps = {
      sex: "No, male, female.".age: 18,}function handle() {}const result = { name: "Liu".age: 18.handle: handle }



    ReactDOM.render(<Parson {. result} / >.document.getElementById('app1'))
Copy the code

Props to summarize

// Do not change the props value to read-only inside the component


// You can use {... Obj} to batch pass
ReactDOM.render(<Parson {. result} / >.document.getElementById('app1'))


// limit the propsClass name. defaultProps = {sex: "No, male, female.".age: 18} or write it inside the class plusstatic


// Functional components can also use props
Copy the code

$refs- Core attributes and event handling for component instances

The string form ref- is no longer recommended and 16.8 still works

So the first thing we have to do is we have two input fields and the first one is to put something in and click on the button and the second one is to put something in and lose focus


		//
    class Parson extends React.Component {
      render() {
        return (
          <div>// add id here<input id="i1" type="text" placeholder="Click the button to output data" />
            <button onClick={this.btn}>Click on my popup left side data</button>
            <input type="text" placeholder="Lost focus output data" />
          </div>
        )
      }
      btn = () = > {
        const i = document.getElementById("i1")  // React is used
        alert(i.value)
      }
    }
    ReactDOM.render(<Parson />.document.getElementById('app1'))
    
    
    
    
   		// Use ref in react
    class Parson extends React.Component {
      render() {
        return (
          <div>/ / use the ref<input ref="input1" type="text" placeholder="Click the button to output data" />
            <button onClick={this.btn1}>Click on my popup left side data</button>
            <input ref="input2" onBlur={this.btn2} type="text" placeholder="Lost focus output data" />
          </div>
        )
      }
      btn1 = () = > {
        console.log(this.refs.input1.value) // refs is used here
      }
      btn2 = () = > {
        console.log(this.refs.input2.value)
      }
    }
    ReactDOM.render(<Parson />.document.getElementById('app1'))
Copy the code

Small problem with the number of ref calls in callback form

Labels must use the ref keyword

    class Parson extends React.Component {
      render() {
        return (
          <div>// go to this and find render<input ref={c= >This. input1 = c} type=" placeholder "placeholder=" placeholder"<button onClick={this.btn1}>Click on my popup left side data</button>
            <input ref={(c)= >{this.input2 = c}} onBlur={this.btn2} type="text" placeholder=" placeholder "/></div>
        )
      }
      btn1 = () = > {
      	console.log(this.input1.value);
      }
      btn2 = () = > {
      	console.log(this.input2.value);
      }
    }
    ReactDOM.render(<Parson />.document.getElementById('app1'))
Copy the code

The callback form directly writes the callback function this to recder to the instance

Minor problem with the number of calls the number of calls to the callback function when written as a callback function and the state has been changed React will call render again and the callback will reset to null before assigning to the function you wrote

When the code is as follows

    class Parson extends React.Component {
      state = {
        isHot: true
      }
      render() {
        const { isHot } = this
        return (
          <div>
            <input ref={c= >{ this.input1 = c; Console. log(" output ", c); }} type="text" /><button onClick={this.btn1}>Click on my popup left side data</button>
            <h1 onClick={this.handleH1}>Weather {isHot? "Very hot" : "cold "}</h1>
          </div>
        )
      }
      btn1 = () = > {
        console.log(this.input1.value);
      }
      handleH1 = () = > {
        this.setState({
          isHot:!this.isHot
        });
      }
    }
    ReactDOM.render(<Parson />.document.getElementById('app1'))
Copy the code

Log will output a output when the page is generated because React executes render once by default

When the and label is clicked, the output is as follows: null is printed because the reder is initialized to NULL when running the function when the state changes

The binding functions in a class that the solution mounts to its own functions can be avoided but in most cases irrelevant

    class Parson extends React.Component {
      state = {
        isHot: true
      }
      render() {
        const { isHot } = this
        return (
          <div>
            <input ref={this.saveInput} type="text" />
            <button onClick={this.btn1}>Click on my popup left side data</button>
            <h1 onClick={this.handleH1}>{this.state.ishot? "Very hot" : "cold "}</h1>
          </div>
        )
      }
      saveInput = (c) = >{
        this.input1 = c
        console.log("Output",c);
      }
      btn1 = () = > {
        console.log(this.input1.value);
      }
      handleH1 = () = > {
        this.setState({
          isHot:!this.state.isHot
        });
      }
    }
    ReactDOM.render(<Parson />.document.getElementById('app1'))
Copy the code

The use of createRef

    class Parson extends React.Component {
      myRef1 = React.createRef() // Returns a container that stores the nodes identified by ref
      // is equal to I made a container hanging on the instance itself named myRef
      // Only one container can be stored in the container
      myRef2 = React.createRef()
      state = {
        isHot: true
      }
      render() {
        const { isHot } = this
        return (
          <div>
            <input ref={this.myRef1} type="text" />{/* React.createRef() creates a container and stores the current node in the container */}<input ref={this.myRef2} onBlur={this.handle2} type="text" />
            <button onClick={this.handle1}>Click on my popup left side data</button>
          </div>
        )
      }
      handle1 = () = > {
        console.log(this.myRef1.current); // React generates current for you
      }
      handle2 = () = > {
        console.log(this.myRef2.current);
      }
    }
    ReactDOM.render(<Parson />.document.getElementById('app1'))
Copy the code

Example 2

    class Parson extends React.Component {

      myRef = {
        myRef1:React.createRef(),
        myRef2:React.createRef()
      }
      state = {
        isHot: true
      }
      
      render() {
        const { isHot } = this.state

        // Try the structure here and it doesn't work
        // One at a time
        const {myRef1,myRef2} = this.myRef
        return (
          <div>
            <input ref={myRef1} type="text" />{/* React.createRef() creates a container and stores the current node in the container */}<input ref={myRef2} onBlur={this.handle2} type="text" />
            <button onClick={this.handle1}>Click on my popup left side data</button>
          </div>
        )
      }
      handle1 = () = > {
        console.log(this.myRef.myRef1.current); // React generates current for you
      }
      handle2 = () = > {
        console.log(this.myRef.myRef2.current);
      }
    }
    ReactDOM.render(<Parson />.document.getElementById('app1'))
Copy the code

Event handling can be done with target instead of refs

  1. Use the onXxx property to specify event handlers (case sensitive). Instead of using the element DOM events – encapsulated for better compatibility, events in B. React are handled by event delegates (delegated to the outermost element of the component) – for efficiency
  2. Get the DOM element object where the event occurred via event.target

Collect form data

Controlled uncontrolled components

The managed component uses the DOM of the fetch input class as your input is maintained into the state and fetched directly from the state when needed

    class Login extends React.Component {

      state = {
        username:' '.password:' '
      }
      render() {
        return (
          <div>
            <form action="" onSubmit={this.handleSubmit}>The user name<input onChange={this.saveUsername} type="text" name="username" />password<input onChange={this.savePassword} type="password" name="password" />
              <button>landing</button>
            </form>
          </div>
        )
      }
      saveUsername = (e) = > {
        this.setState({
          username:e.target.value
        })
      }
      savePassword = (e) = > {
        this.setState({
          password:e.target.value
        })
      }
      handleSubmit = (e) = > {
      	// Print the address of the action that will be forwarded to the form
        e.preventDefault() // Block the default event to block form submission
        const {username,password} = this.state
        console.log(username,password);
      }
    }
    ReactDOM.render(<Login />.document.getElementById('app1'))
Copy the code

Uncontrolled use of ref to get the current value of the node

A lot of them are written using currization

If I wanted to log in, I could write it like this

    class Login extends React.Component {

      state = {
        username:' '.password:' '
      }
      render() {
        return (
          <div>
            <form action="" onSubmit={this.handleSubmit}>The user name<input onChange={this.saveUsername} type="text" name="username" />password<input onChange={this.savePassword} type="password" name="password" />
              <button>landing</button>
            </form>
          </div>
        )
      }
      saveUsername = (e) = > {
        this.setState({
          username:e.target.value
        })
      }
      savePassword = (e) = > {
        this.setState({
          password:e.target.value
        })
      }
      handleSubmit = (e) = > {
        e.preventDefault() // Block the default event to block form submission
        const {username,password} = this.state
        console.log(username,password);
      }
    }
    ReactDOM.render(<Login />.document.getElementById('app1'))
Copy the code

But if I’m going to register my phone and I have a lot of information that’s just too bloated to write

The first method is passed in when the event is triggeredclass Login extends React.Component {

      state = {
        username: ' '.password: ' '
      }
      render() {
        return (
          <div>
            <form action="" onSubmit={this.handleSubmit}>The user name<input onChange={(e)= >This.saveformdata ('username',e)} type="text" name="username" /> Password<input onChange={(e)= >this.saveFormData('password',e)} type="password" name="password" />
              <button>landing</button>
            </form>
          </div>)}// Save the form data to state
      saveFormData = (v,e) = > {
        console.log(v,e.target.value);
        this.setState({
          [v]:e.target.value // Add [] or else you won't read variable data as a 'v' string
        })
      }
    }
    ReactDOM.render(<Login />.document.getElementById('app1') -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --// The second one starts with the pass in username function
    class Login extends React.Component {

      state = {
        username: ' '.password: ' '
      }
      render() {
        return (
          <div>
            <form action="" onSubmit={this.handleSubmit}>// select * from user where username = 'username'<input onChange={this.saveFormData('username')} type="text" name="username" />password<input onChange={this.saveFormData('password')} type="password" name="password" />
              <button>landing</button>
            </form>
          </div>)}// When the event is raised in return
      saveFormData = (v) = > {
        //console.log(v);
        return (e) = > {
          console.log(v,e.target.value);
          this.setState({
            [v]:e.target.value
          })
        }
      }
    }
    ReactDOM.render(<Login />.document.getElementById('app1'))
Copy the code

Component life cycle

The basic use

Basic componentDidMount componentWillUnmount unload components ReactDOM. UnmountComponentAtNode (document. GetElementById (‘ app1))

    class Life extends React.Component {
      / / state
      state = {
        opacity: 1
      }
      // State update during initialization
      render() {
        const { opacity } = this.state
        return (
          <div>
            <h2 style={{ opacity: opacity}} >What if you can't React?</h2>
            <button onClick={this.death}>No way!</button>
          </div>)}// The lifecycle component does not need to be called when it is mounted because it is not used as a callback
      // The component is mounted
      componentDidMount() {
        this.timer = setInterval(() = > {
          let { opacity } = this.state
          opacity += 1
          if (opacity <= 0) opacity = 1
          this.setState({
            opacity
          })
        }, 200);
      }
      // The component will be uninstalled
      componentWillUnmount() {
        clearTimeout(this.timer)
      }
      death = () = > {
        // You can also turn off the timer here

        // Uninstall the component
        ReactDOM.unmountComponentAtNode(document.getElementById('app1'))}}// Render to page mount to page mount unmount
    ReactDOM.render(<Life />.document.getElementById('app1'))
Copy the code

Order of components

Constructor componentWillMount components will mount render componentDidMount components mounted Using ReactDOM. UnmountComponentAtNode () will adjust this function before unloading ComponentWillUnmount The component is about to be unmountedCopy the code

When setState() is called

ShouldComponentUpdate () Specifies the hook to be updated. Shouldcomponentwillupdate render Specifies the hook to be updated componentDidUpdateCopy the code

When forceUpdate() is called to force an update

There’s a valve less than the update and you don’t want to make any changes to the state like let you update and just use this

Component to be updated hook componentWillUpdate Render component updated hook componentDidUpdateCopy the code

Summary of the code

    // Create a component
    class Life extends React.Component {

      / / the constructor
      constructor(props) {
        super(props)
        console.log('Life-constructor');

        // Initialization state
        this.state = {
          count: 0}}render() {
        console.log('Life-render');
        const {
          count
        } = this.state
        return (
          <div>
            <h2>The current sum is {count}</h2>
            <button onClick={this.add}>Gal.</button>
            <button onClick={this.force}>Forced to update</button>
          </div>)}// The component will be mounted
      componentWillMount() {
        console.log('Life-componentWillMount');
      }
      // The component is mounted
      componentDidMount() {
        console.log('Life-componentDidMount');
      }



      //------------------------------------------------------------------------------

      // When setState calls return true by default, false does not go down
        				// The props and state to be changed next
      shouldComponentUpdate(nextProps,nextState) {
        console.log('Life-shouldComponentUpdate');
        return true
      }
      // The hook that the component will update
      componentWillUpdate() {
        console.log('Life-componentWillUpdate');
      }
      // The component's updated hook
      componentDidUpdate() {
        console.log('Life-componentDidUpdate');
      }

      //------------------------------------------------------------------------------



      // Before uninstallation
      componentWillUnmount() {
        console.log('Life-componentWillUnmount');
      }

      add = () = > {
        let { count } = this.state
        this.setState({
          count: count + 1
        })
      }
      force = () = > {
        this.forceUpdate()
      }
    }
    // Render component
    ReactDOM.render(<Life />.document.getElementById('app1'))
Copy the code

Parent component Render process

First paste the code A component name to B component display

    class A extends React.Component {
      state = {
        carName: 'Mercedes'  //A components are defined and not displayed
      }
      render() {
        return (
          <div>
            <div>A</div>{/* Cars in A state are not displayed */}<button onClick={this.changeCar}>To change</button>
            <B {. this.state} / >
          </div>
        )
      }
      changeCar = () = > {
        this.setState({
          carName: 'otto'}}})class B extends React.Component {
      componentWillReceiveProps(props){
        console.log('child components will accept the label attribute (parameters) componentWillReceiveProps',props);
      }
      render() {
        console.log(this.props);
        return (
          <div>
            <div>B</div>
            <div>{this.props.carName}</div>{/* The car passed by A is displayed in the B component */}</div>)}}// Render component
    ReactDOM.render(<A />.document.getElementById('app1'))
Copy the code

The life cycle

Once the render of the parent component executes, The child component will execute component will accept the label attribute (parameters) componentWillReceiveProps (props) but you will find that the parent component of props for the first time coming (when is page rendering) for the first time will not call again the props value of the parent component ShouldComponentUpdate () returns the valve by defaulttrueComponentWillUpdate hook componentDidUpdate(preProps,preState)Copy the code

New release lifecycle

Hooks to be deprecated in the new version

The following three front to add UNSAFE_ componentWillMount componentWillUpdate componentWillReceiveProps (props) but will be abandoned Don't use these three so it's best to the new versionCopy the code

The new usage scenarios are extremely rare, so the most common ones are only three DidMount DidUpdate WillUnmount

New version of hook usage

Static getDerivedStateFromProps(props, State){// Return a state object or null // If a state object is returned, the component state is equal to the object value and the value cannot be modified // If the value of state is dependent on props at any time, then you can use, Return null return {props} return {name:" hello "}} // But this component makes the code difficult to maintain, etc. So use scenarios are extremely rare. This function does something before updating GetSnapshotBeforeUpdate (){return Snapshot value Return value is passed to componentDidUpdate(preProps,preState,v) with the third argument}Copy the code

React application (via scaffolding)

The basic use

  1. Install NPM i-g create-react-app
  2. Go to the directory where you want to create the project and run create-react-app hello-react
  3. Enter the CD hello – react
  4. Start the project NPM start yarn start Enable the developer server without yarn installed NPM start yarn Build Generate the final static file yarn eject Expose all webPack configuration files (this operation is irreversible)

File to read

Json Application shell configuration Robots. TXT crawler rule file SRC app.css app.js app.test. js Test file index.js entry file Setuptests.js component testCopy the code

index.html

<html lang="en">
  <head>
    <meta charset="utf-8" />
    <! -- %PUBLIC_URL% represents the path of the public folder -->
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <! -- Enable ideal viewport mobile adaptation -->
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <! -- Configure the color of the browser TAB + address bar (only supports Android mobile browsers and not very compatible) -->
    <meta name="theme-color" content="# 000000" />
    <! -- Search Engine Optimization -->
    <meta
      name="description"
      content="Web site created using create-react-app"
    />
    <! -- Apple Browser logo added to the home page -->
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
    <! -- Configuration related to application shell -->
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <title>React App</title>
  </head>
  <body>
    <! -- If the browser does not support the execution of javascript script -->
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <! -- -- -- > container
    <div id="root"></div>
  </body>
</html>
Copy the code

Index. Js interpretation

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App'; / / component
import reportWebVitals from './reportWebVitals';

ReactDOM.render(
  <React.StrictMode>// There will be an error when adding this component<App />
  </React.StrictMode>.document.getElementById('root')); reportWebVitals();// Record page performance
Copy the code

Conflict styles

You can use modularity

Hello.js hello.css Rename hello.css to hello.module. CSS and import import hello from './hello.module. CSS '<div in hello.js className={hello. Your style name}></div>Copy the code

You can also write styles using less

hello{
	.balbala{
	
	}
}
Copy the code

Plug-in installation tips

Install vs plugin ES7 React/story/GraphQL/React – Native snippets initialization RCC directly

Small case – Composite use of components

Input box list select all delete regions

A component list. Each item in the component list is a component. The delete field is a component

Child components pass values to parent components

The parent component binds a function to the child component propertyexport default class Father extends Component{
  render(){
    return(
      <div>
        <Son handle={this.handle} />
      </div>
    )
  }
  handle = (data) = >The {log(data)}} child component is called directlythis.props. Hanlde (Pass the value to the parent component to get it)Copy the code

The plug-in generates a unique key

The plug-in name nanoid is smaller than the UUID NPM I Nanoid is introduced when used

import {nanoid} from 'nanoid'

log(nanoid())
Copy the code

TodoList case summary

  1. Split components, implement static components, note the className, style notation
  2. Dynamic initialization list, how to determine which component to put data in state? — Used by a component: placed in its own state — used by a component: placed in their parent component’s state (officially called: state promotion)
  3. Parent component communication — the parent component passes to the child component via props — the child component passes to the parent component via props, but the parent component passes functions to the child component in advance
  4. Note the difference between defaultCheckd and value
  5. Where is the state? Where is the way to manipulate the state

React Ajax sends requests

A quick review of Axios and Node

node

const { response } = require('express');
const express = require('express')
const app = express()

app.use((request,response,next) = >{
  console.log('Someone has requested server 1');
  next()
})

app.get('/students'.(request,response) = >{
  const students = [
    {id:'001'.name:'tom'.age:18},
    {id:'002'.name:'jerry'.age:19},
    {id:'003'.name:'tony'.age:20},
  ]
  response.send(students)
})

app.listen(5000.(err) = >{
  if(! err){console.log('Successful startup can request student data! ');}
})
Copy the code

axios

The first one, BTN is equal toasync() = > {const result = await axios.get('http://localhost:5000/students')
      .catch((err) = > {console.log(err); $axios.get();'http://localhost:5000/students')
    .then((response) = >{},(err) = >{}). Then the first of the two functions succeedsCopy the code

The react cross-domain

Proxy cross domain you 3000 send 5000 can but when the data back will be ajax interception, proxy without Ajax blocking your own 3000 port —– proxy port 3000 —– server 5000

Receive mobile phone you look for the teacher he does not give you, you look for parents to look for the teacher to take a mobile phone, parents are giving you the parent is the agent, you are the current address, the teacher is the request address

Suppose you are3000The teacher is5000

1.Add a sentence to package.json"proxy":"http://localhost:5000" // Address + port

2.Restart the project3.Make a request to your own portCopy the code

If you want to send a request to multiple addresses such as 5001, the scaffolding will open 3000 for you, and you request 3000/index.html. If you want to send a request to multiple addresses such as 5001, the scaffolding will open 3000 for you

Delete the previous package.json"proxy":"http://localhost:5000 "add a new file to SRC: setupproxy.js // introduce a built-in module that is available when react is initialized to const proxy = Require ('http-proxy-middleware') module.exports = function(app) {app.use(proxy('/api1',{// meet /api1), Target :'http://localhost:5000', // to whom the request is forwarded changeOrigin:true, // default is false, Request. Get ('Host') = 5000 If false: 3000 pathRewrite:{'^/ API1 ':'}} proxy('/api2',{ target:'http://localhost:5001', changeOrigin:true, PathRewrite: {' ^ / api2 ':'} / / detect api2 went 5001}})) send request with api1 or 2 will automatically convert $axios. Get (' http://localhost:3000/api1/students')  $axios.get('http://localhost:3000/api2/cars')Copy the code

React Cross-domain approach summary

Methods a

Add the following configuration to package.json

"proxy":"http://localhost:5000"
Copy the code

Description:

  1. Advantages: Simple configuration and no prefix can be added when the front-end requests resources.
  2. Disadvantages: You cannot configure multiple agents.
  3. How it works: Configure the proxy so that when 3000 resources are requested that do not exist, the request is forwarded to 5000 (matching front-end resources is preferred).

Method 2

  1. Step 1: Create the proxy profile
Create a configuration file under SRC: SRC/setupproxy.jsCopy the code
  1. Write setupproxy.js to configure specific proxy rules:
   const proxy = require('http-proxy-middleware')
   
   module.exports = function(app) {
     app.use(
       proxy('/api1', {  // API1 is the request that needs to be forwarded (all requests with/API1 prefix are forwarded to 5000)
         target: 'http://localhost:5000'.// Configure the forwarding target address (the server address that can return data)
         changeOrigin: true.// Controls the value of the host field in the request header received by the server
         /* When changeOrigin is set to true, the host in the request header received by the server is: localhost:5000 The default changeOrigin value is false, but we usually set the changeOrigin value to true */
         pathRewrite: {'^/api1': ' '} // Remove the request prefix to ensure that the backend server is normal request address (must be configured)
       }),
       proxy('/api2', { 
         target: 'http://localhost:5001'.changeOrigin: true.pathRewrite: {'^/api2': ' '}}}))Copy the code

Description:

  1. Advantages: Multiple proxies can be configured to flexibly control whether requests go through proxies.
  2. Disadvantages: Cumbersome configuration and prefix must be added when the front-end requests resources.

Small case study – Github search

JSX can only write expressions such as ternary and not statements such as if

So when I write the method I'm going to define in the parent component of my App what I'm going to get for my parameters and I'm going to get this many things from the search component state = {users: [].// List of users
    isFirst: true.// Whether to open the page for the first time
    isLoading: false.// The request is waiting
    err: ' '.// Store request error information} do I need to write so many methods to put in? This directly// Update app status
  updateAppState = (stateObj) = > {
    this.setState(stateObj)} setState is written to return an object directlyCopy the code

JSX can only write expressions such as ternary and not statements such as if

Only expression ternary checkerings can be written to determinerender() {
    const { users,isFirst,isLoading,err } = this.props
    return (
      <div className="row">
        {
          isFirst ? <h2>Is this your first use? Welcome to use</h2> :
          isLoading ? <h2>Is the data request completed? Loading.....................</h2> :
          err ? <h2>Is there an error?<h2/> :
          users.map((userItem, i, arr) => {
            return <Item userItem={userItem} key={userItem.id} />})}</div>)}Copy the code

The error object is saved when the request comes back

    axios.get(`https://api.github.com/search/users1`, {
      params: { q: value }
    }).then((result) = > {
      this.props.updateAppState({
        isLoading: false.users: result.data.items
      })
    },(err) = > {
      console.log(typeof err);
      this.props.updateAppState({
        isLoading: false.err:err    / /!!!!!!!!!!!!!! That's not going to work because it's an object and it's not going to render and it's going to store err's message
        err:err.message
      })
    })
Copy the code

Any component pass-message subscription-publish mechanism

PubSubJS

Download the package NPM I pubsub-js or YARN Add Pubsub-js Subscribe messages Subscribe messages to whoever receives messagesvar mySubscriber = function(msg,data){
	log(msg,data)
}
var token = PubSub.subscribe('MY TOPIC',mySubscriber) / / subscribeorvar token = PubSub.subscribe('getMainValue'.(msg, data) = >{
    console.log('data',data);
})

PubSub.unsubscribe(token) // Clear the subscription· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·// Components subscribe as soon as they are placed on the page, so put them in componentDidMount instead of Update
PubSub.publish('MY TOPIC'.'hello word! 'The helloWord here will be passed to the data aboveCopy the code

Token writes to this as follows:

  // Subscribe as soon as the component is placed on the page
  componentDidMount() {
    this.token = PubSub.subscribe('getMainValue'.(msg, data) = > {
      this.setState(data)
    })
  }
  / / unloading
  componentWillUnmount(){
    PubSub.unsubscribe(this.token)
  }
Copy the code

Fetch sends a request

How many ways are there to send a request?

  1. XMLHttpRequest on XHR //window
  2. JQuery // Inferior callback hell
  3. Axios // Promise style no callback hell

The front-end JQ and AXIos are both wrapped XHR and the back-end HTTP JQ wrapped by AXIos. Axios is both a third-party library, and the fetch on window is not a third-party library and it is also promise style

Basic usage comparison



    // The data in the input box can be searched for github users by following the link below
    const { inputRef: { value } } = this
    
    axios.get(`https://api.github.com/search/users`, {
      params: { q: value }
    }).then(
    	result= > {},
        err= >{}) -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --const { inputRef: { value } } = this

	/ / short
    fetch(`https://api.github.com/search/users?q=${value}`).then(
      res= > {
        return res.json()	// The data must be in then to get
      },
      err= > {
      	return new Promise(() = >{})
      }
    ).then(
          res= > {
            console.log('Obtain success', res);
          },
          err= > {
            console.log('Fetch failed', err.message); })// abbreviation unified handling error
    fetch(`https://api.github.com/search/users?q=${value}`).then(
      res= > res.json()
    ).then(
      res= > { console.log('Data obtained successfully', res) }
	).catch( // Handle errors uniformly
	  err= > {console.log(err.message)}
	)
	
	// async await
	try{
        const response = await fetch(`https://api.github.com/search/users?q=${value}`)
        const data = await response.json() //await can only be followed by promise, but response.json() is really a promise
        console.log(data)
	}catch(err){ //await does not catch errors so catch them here
		console.log(err.message)
	}
	

    // Focus on separation
    fetch(`https://api.github.com/search/users?q=${value}`).then(
      // It is only used to check whether the connection can be made even if 404 succeeds
      res= > {
        // console.log(' Server contacted successfully, but no data ', res);
        Json () returns a promise in res.json()
        // console.log('res.json()',res.json());
        // Direct then() is too messy so return returns in then
        return res.json() Res.json () returns a promise
      },
      404 will not go because 404 means there is no resource but it is connected
      err= > { 
      	console.log('Failed to contact server', err);
      	// Return promise, then executes. Return non-promise, success and output
      	// So if you don't write return, it will return underined by default
      	// Return an initialized promise instance and no further progress will be made
      	return new Promise(() = >{})
      }
    ).then( // the previous res.json() returns a promise, so then is caught
          res= > {
            // console.log(' succeeded ', res);
          },
          err= > {
            // console.log(' failed to get ', err.message);})Copy the code

The React routing

An understanding of routing

A route is a mapping. Key :value For example, /home is not a link path

  1. Router. get(path,(request,response) => {}) When node receives a request, it finds a matching route based on the request path. Call functions in the route to process the request and return response data
  2. The value of the browser is component, which displays the content of the page. When the path of the browser changes to /home, The current routing component will become the Test component in two modes: one is history mode introduced by H5 BrowserRouter, a monitoring hash(anchor point) value change event HashRouter

React -router-dom Navlink is used

React router is a plugin library for React. This library is used to implement a SPA application in most react based projects, but cannot be introduced directly. There are three uses for this library: Web React-router-dom native Any There are two modes BrowserRouter/HashRouterimport { BrowserRouter, Link, Route } from 'react-router-dom';


// Outside 
      
        is an error
      
// Write routing links
<BrowserRouter>// Route link //to better write it in lower case<Link to="/about">About</Link>
    <Link to="/home">Home</Link>
</BrowserRouter>

// Outside 
      
        is an error
      
// Register the route
<BrowserRouter>
    <Route path="/about" component={About} />
    <Route path="/home" component={Home} />
</BrowserRouter>



// Enclosing 
      
        is incorrect because a 
       
         tag is only one
       
      
// If you write two, they are independent and not together
// So the entire 
      
        tag is wrapped around the route link and the registered route
      So you don't need to import BrowserRouter in the component. You just need Link and Route to put <BrowserRouter> in the index.js main file.<BrowserRouter><App /></BrowserRouter>.document.getElementById('root'));


Copy the code

In summary, route links automatically append styles

2. Change the Link in the navigation area to Link <Link to="/ XXXX "> XXXX </Link> 3. Match write paths in the function pane <Route path="/ XXXX "Component ={XXXX} /> 4. The outermost part of the main <App/> file wraps either <BrowserRouter> or <HashRouter> 5. If you want to style it instead of using Link use Navlink by default append the active style when clicked or use the activeClassName property to define < Navlink activeClassName="active" to="/about">About</NavLink>Copy the code

Routing components and common components

  1. Location Different General components in Component Routing components in the Pages folder

The basic component does not pass data to it. Then its Props does not pass data to it. The routing component takes three fixed parameters

ƒ go(n) goBack: ƒ goBack() goForward: ƒ goForward() push: ƒ push(path, state) replace: ƒ replace(path, state) history: pathname: "/about" search: "state: undefined history: params: {} path: "/about" url: "/about"Copy the code

Wrap route link Navlink tag body content is a special tag attribute children

<NavLink activeClassName="active" className="item" to="/about">About</NavLink>
<NavLink activeClassName="active" className="item" to="/about">About</NavLink>There are too many redundant things to write activeClassName="active" className="item"So encapsulate your own component <MyNavLink to="/home"> just write to <MyNavLink/>Copy the code

So the encapsulation

import React, { Component } from 'react'
import {NavLink} from 'react-router-dom'

export default class MyNavLink extends Component {
  render() {
    return (
      <NavLink activeClassName="active" className="list-group-item" {. this.props} >
        {/*this.props.children*/}
      </NavLink>}} To write routing links elsewhere just <MyNavLink to="/about">About</MyNavLink>
<MyNavLink to="/Home">Home</MyNavLink>The value in the tag is also passed as an attribute to the component's props with the key childrenCopy the code

Routing Swich

  1. There is usually a one-to-one correspondence between Path and Component
  2. Switch improves route matching efficiency (Single match)
<div>
    <MyNavLink to='/home' children='home' />
    <MyNavLink to='/about' children='about' />
    <MyNavLink to='/test' children='test' />


    <Route path='/home' component={Home} />
    <Route path='/about' component={About} />
    <Route path='/about' component={Test} />// Both routes will be rendered because finding /about will look down // so importing the Switch tag from the route will not look down the route</div>


import { Route,Switch } from 'react-router-dom';

<Switch>
    <Route path='/home' component={Home} />
    <Route path='/about' component={About} />
    <Route path='/about' component={Test} />
</Switch>
Copy the code

Style loss problem

The scaffolding startup will use webpack’s devServer to open a local url that points to the public folder and by default takes index.html and if you modify it to point to a path that doesn’t exist it will return index.html by default

When the route is multilevel and introduces a resource in public it will be lost if you refresh the page and add your first level path to the resource path because if you modify it to point to a path that doesn't exist then it will return index.html <MyNavLink to= by default'/first/home' children='home' />
<MyNavLink to='/first/about' children='about' />

<Route path='/first/home' component={Home} />
<Route path='/first/about' component={About} />If it is multi-level /first/home and the main file index. HTML introduces CSS in public <link rel="stylesheet" href="./bootstrap.css"> page refresh, request will take the /first pathCopy the code

The solution

The first way/ / remove the point logic as localhost: 3000 / bootstrap CSS
					// instead of the current path of./
<link rel="stylesheet" href="/bootstrap.css"> the second// The absolute path of public only applies to react scaffolding
<link rel="stylesheet" href="%PUBLIC_URL%/bootstrap.css"> 3 uses hash routingCopy the code

Fuzzy matching and strict pattern

In general, do not enable strict matching unless the route hop is not correct. If this function is enabled, level-2 routes cannot be matched

<MyNavLink to='/home' children='home' />
<Route path='/a/b/home' component={Home} /><MyNavLink to='/a/home' children='home' />
<Route path='/home' component={Home} />Matched on fuzzy match <MyNavLink to='/home/a/b' children='home' />
<Route path='/home' component={Home} />

// Exact ={true} indicates that exact matching must be the same when registering routes
<MyNavLink to='/home' children='home' />
<Route exact path='/a/b/home' component={Home} />
<Route exact={true} path='/a/b/home' component={Home} />
Copy the code

Route Redirect

It is written at the bottom of all route registrations. When all routes fail to match, the route specified by the Redirect is redirected

<div>
    <MyNavLink to='/home' children='home' />
    <MyNavLink to='/about' children='about' />

    <Switch>
    <Route path='/home' component={Home} />
    <Route path='/about' component={About} />
    <Redirect to='/about' />
    </Switch>
</div>If you can't match the Redirect, turn to the RedirectCopy the code

Embedded routines by

When registering child routes, set the path value of the parent route. Routes are matched in the order of registering routes. Routes are first matched in the parent component

Home News Message Home<div>
          <MyNavLink to='/Home/News'>News</MyNavLink>
          <MyNavLink to='/Home/Message'>Message</MyNavLink>
        </div>

        <div className='two'>
          <Route path='/Home/News' component={News}></Route>
          <Route path='/Home/Message' component={Message}></Route>
          <Redirect to='/Home/News'></Redirect>
        </div>

Copy the code

The routing component passes the Params parameter

Routing links (with parameters)<Link to={` /home/message/detail/ parameters1/ parameters2} >Register route (declare receiving)<Route path='/home/message/detail/: key of parameter 1 /: key of parameter 2 ' component={xxx}></Route>Accept the parameter this.props. Match.paramsCopy the code

code

export default class Message extends Component {
  state = {
    MessageList: [{id: '01'.title: News' 1 ' },
      { id: '02'.title: News' 2 ' },
      { id: '03'.title: 'the message 3']}},render() {
    return (
      <div>
        {
          this.state.MessageList.map((v, i, arr) => {
            return (
              <li key={v.id}>{/* Pass the params parameter to the routing component. Here we have to package a {} because the template string is something in JS.<Link to={` /home/message/detail/ ${v.id} / ${v.title} `} >{v.title}</Link>
              </li>)})}<hr />{/* Declare the key that accepts the params argument */}<Route path='/home/message/detail/:id/:title' component={Detail}></Route>
      </div>)}} subcomponent path='/home/message/detail/:id/:title'The acceptance parameters are in propsconst DetailData = [
  { id: '01'.content: 'China' },
  { id: '02'.content: 'hello' },
  { id: '03'.content: 'his'},]export default class Detail extends Component {
  render() {
    const { id,title } = this.props.match.params // This accepts the params parameter
    const {content} = DetailData.find((v) = > {
      return v.id === id
    })
    return (
      <ul>
        <li>{id}</li>
        <li>{title}</li>
        <li>{content}</li>
      </ul>)}}Copy the code

The routing component passes the search parameter

Routing links (with parameters)<Link to={` /home/message/detail/?id=${v.id}&title=${v.title}`} >{v.title}</Link>Registered routing (statement receiving) without receiving receive parameters. This props. The location. The search can get such a urlencoded code? Id =01&title= message 1 React automatically helps you download a library named queryString short QS two methods qs.parse(XXX) qs.stringify(XXX) so receive arguments are // because there will be a question mark so sclice truncates the first qs.parse(this.props.location.search.slice(1));Copy the code

The routing component passes the state parameter regardless of the state

Refreshing can also preserve parameters

Routing links (with parameters) are written as objects<Link to={{ pathname: '/home/message/detail', state: { id: v.id.title: v.title } }}>{v.title}</Link>Registered routing (statement receiving) do not need to register to receive normal component receives parameter = this. Props. The location. The state | | is undefinedCopy the code

Push pattern and replace pattern

One to replace one to push

The routing records are placed one by one in the innermost replace mode to replace the top of the two open modes <Link replace to='/xxxx'></Link>
<Link replace={true} to='/xxxx'></Link>
Copy the code

Programmatic routing navigation

The base component doesn’t give it any data so its props doesn’t have anything and the routing component takes three fixed arguments history Location match and in history there are two methods push and replace

Params <button onClick={() = > this.pushshow (v.id, v.tate)}>push </button><button onClick={()= >Enclosing replaceShow (v.i d, v.t itle)} > replace view</button>

pushShow = (id, title) = > {
	/ / params parameters
	this.props.history.push(`/home/message/detail/${id}/${title}`)
	/ / search parameters
    this.props.history.push(`/home/message/detail? id=${id}&title=${title}`)
    / / state parameters
    this.props.history.push(`/home/message/detail`, {id:id,title:title})
}
replaceShow = (id, title) = > {
	this.props.history.replace(`/home/message/detail/${id}/${title}`)}Copy the code

History also has a way of going forward and backward

<button onClick={this. The back} > back < / button ><button onClick={this.forward}>forward</button>

back = (params) = > {
	this.props.history.goBack()
}
forward = (params) = > {
	this.props.history.goForward()
}
forward = (params) = > {
	this.props.history.go(2) // go back
}
Copy the code

withRouter

General components do not have apis on history and are processed into routing components using withRouter

import {withRouter } from 'react-router-dom';

class App extends Component {
  render() {
    return (
      <div>
      	<button onClick={this.back}>The fallback</button>
      </div>
    )
  }
  back = (params) = > {
    this.props.history.goBack()
  }
}

export default withRouter(App) // Process returns a new component for the routing component
Copy the code

History is different from hash

  1. BrowserRouter uses the H5 History API. Hash Routers that are incompatible with IE9 and below use URL hashes
  2. Addresses in hash mode have #
  3. The state of the BrowserRouter is not lost after the page is refreshed, because the hash loses state if it is in the history object

Project package run

Injection.injection.js: $injection.injection.js: $injection.injection.js: $injection.injection.js: $injection.injection.js: $injection.injection.js Check to see if you are using BrowserRouter (the same as Vue's history mode) and need the backend configuration support, otherwise use HashRouter (with #). ------------------------------- or use a library serve NPM I serve -g and then directly serve in the path. If you want to go to the current a folder, you can directly CD there or you can serve a serve./aCopy the code

Expand the knowledge

SetState’s callback function is similar to nextTick()

Object type

// The callback is called after the status update and after the render update
this.setState( {} , callback )


export default class About extends Component {
  render() {
    return (
      <div>
        <h3>I'm About</h3>
        <h1>The current sum is {this.state.count}</h1>
        <button onClick={this.add}>I + 1 point</button>
      </div>
    )
  }
  state = {
    count: 0
  }
  add = () = > {
    const { count } = this.state

    this.setState({ // an asynchronous thread will be opened to help you change
      count:count+1
    },() = > {  // The callback is called after the status update and after the render update
      console.log('callback'.this.state);
    })

    console.log('normal'.this.state); // React is an asynchronous thread}} Normal output after clicking button {count: 0{of} callbackcount: 1}
Copy the code

functional

	
	this.setState( (state,props) = >{ return } , callback )



    this.setState((state,props) = > {
      return {count:state.count+1}},() = > {
      // The callback function
    })
    
    this.setState((state,props) = > ({count:state.count+1}) , [callback] )
Copy the code

Objects are just syntactic sugar for functions

Suspense lazyload

// Introduce the lazy function
import React, { Component, lazy } from 'react';
import { Route, Switch, withRouter } from 'react-router-dom';
//lazy wraps the import component
const Home = lazy(() = > import('./pages/Home'))
const About = lazy(() = > import('./pages/About'))

class App extends Component {
  render() {
    return (
      <div>

        <MyNavLink to='/home' children='home page'></MyNavLink>
        <MyNavLink to='/about'>The about page</MyNavLink>

        <Switch>
          <Route path='/home' component={Home}></Route>
          <Route path='/about' component={About}></Route>
        </Switch>
      </div>)}}export defaultWithRouter (App) does this because it will wait forever if the connection is slow. You must set up a component for load time Suspense/ / into the Suspense
import React, { Component, lazy ,Suspense } from 'react';

Suspense tags wrap routing placeholders
The Suspense tag's fallback attribute is a wait-time component and cannot be lazily loaded
<Suspense fallback={<h1>Loading</h1>} ><Switch>
        <Route path='/home' component={Home}></Route>
        <Route path='/about/:abcdd' component={About}></Route>
    </Switch>
</Suspense>





			/ / for finally
const Home = lazy(() = > import('./pages/Home'))
const About = lazy(() = > import('./pages/About'))

class App extends Component {
  render() {
    return (
      <div>

        <NavLink to='/home'>The home page</NavLink>
        <NavLink to='/about'>The about page</NavLink>

        <Suspense fallback={<h1>Loading</h1>} ><Switch>
            <Route path='/home' component={Home}></Route>
            <Route path='/about' component={About}></Route>
          </Switch>
        </Suspense>
      </div>)}}Copy the code

Hooks

New features/syntax in Act 16.8 let you use state and other React features in function components

First look at the differencesimport React from 'react'
/ / function type
function Fun1() {
  function btn(){
    console.log('btn');
  }
  return (
    <div>
      <h1>Digital {}</h1>Cannot be used without state<button onClick={btn}>I + 1 point</button>
    </div>)}// Class components
class Fun2 extends React.Component {
  render() {
    return (
      <div>
        <h1>Digital {this. State. Num}</h1>
        <button onClick={this.btn}>I + 1 point</button>
      </div>
    )
  }
  state = {
    num: 0
  }
  btn = () = > {
    this.setState(state= > ({ num: state.num + 1}}}))export default Fun1

Copy the code

State Hooks

Make function components stateful and read and write

Using react.usestate (value) in a functional component returns a 2-bit array. Deconstructing the array returns two arguments, the first for the value you passed in and the second for the method that operated on it. // Function Fun1() {const [num,setNum] = react. useState(0) function BTN (){setNum((num) => {return num+1 SetNum (num => num +1)} return (<div> <h1> num) </h1> <button onClick={BTN}> </div>) } this function will be called 1+n times every time the value changes as you click on it, but every time it does React. UseState (0) that value will always be 0Copy the code

Effect Hooks Life cycle Hooks

Write directly in the function component function

React.useEffect(() = >{log(equivalent to render)}) React. UseEffect (() = >{log(equivalent to didmount)},[]) react.useeffect (() = >},[num,name]) react. useEffect(() = > {
    let timer = setInterval(()={
    	xxxxxxxx
    },1000)
    return () = >{ clearInterval(timer) } // The returned willUnmount will be unmounted}, [])Copy the code

Ref Hooks

Similar and createRef ()

/ / function type
function Fun1(props) {


  const myRef = React.useRef()


  React.useEffect(() = >{})function show(){
    console.log(myRef.current.value);
  }

  return (
    <div>
      <input type="text" ref={myRef} />
      <button onClick={show}>button</button>
    </div>)}Copy the code

Extension API

Fragment

When a tag can also be null the tag can only receive one key attribute but not the other

import {Fragment} from 'react' class xxx extends React.Component { render() { return ( <Fragment key={1}> {this.state.num}</h1> <button onClick={this.btn}> </button> </Fragment>} class XXX extends React.Component { The render () {return (< > < h1 > Numbers {this. State. Num} < / h1 > < button onClick = {this. BTN} > I + 1 < / button > < / a >)}Copy the code

Contex component communication mode

The actual combat generally does not only use it encapsulated third-party kuzu component and descendant component communication

Const XxxContext = react.createcontext () 2. When rendering a component, wrap the xxxContext.provider around it, Provider value={data}> child component </xxxContext.Provider value={data}> 3. The child of the descendant reading data child can also take the first type directly: < xxxContext.consumer > {value => {static contextType = xxxContext // declare to receive this. Context // Read the value of the context. }} </ xxxcontext.consumer >Copy the code

The son component receives the code

const MyContext = React.createContext()  // Create a container object

// Class components
class Fun2 extends React.Component {
  render() {
    return (
      <div>
        <h1>I am the ancestor component</h1>
        <MyContext.Provider value={this.state.name}>{/* Pass can also pass objects */}<FunFather/>
        </MyContext.Provider>
      </div>
    )
  }
  state = {
    name:'hello'}}class FunFather extends React.Component {
  render() {
    console.log(this.context); / / how are you
    return (
      <div>
        <h3>I'm the parent component</h3>
        <FunSon></FunSon>
      </div>)}static contextType = MyContext / / declare
}

// Class child components receive code
class FunSon extends React.Component {
  render() {
    return (
      <h3>I am the son component {this.context}</h3>)}static contextType = MyContext / / declare
}

// The function child component receives code
function FunSon() {
  return (
    <h3>I am the son component<MyContext.Consumer>
        {
          (value) => { return value }
        }
      </MyContext.Consumer>
    </h3>)}Copy the code

PureComponent component optimization

Two problems with Component

  1. As long as setState() is executed, even without changing the state data, rerender == is inefficient
  2. When the current component is rerendered, the child component is automatically rerendered, even if the child component does not use any data from the parent component

It is efficient to re-render only if the state or props data for the current component changes

The reason shouldComponentUpdate in Component always returns true

To solve

ShouldComponentUpdate () method to compare old and new state/props data, return true if there is any change, false if there is no change PureComponent shouldComponentUpdate returns true only if the state or props are changed. This is a shallow comparison. If the internal data of the knowledge data object has changed, return false so do not directly modify the state data, but instead generate new data that cannot be the same addressCopy the code

Solution 1 can only compare the values in the props or state one by one

			// The parameters are props and state to be changed next
  shouldComponentUpdate(nextProps,nextState){
    if(nextState.car === this.state.car){
      // If the next step is the same as the current one, it will not render
      return false
    }
    return true
  }
  
  / / short
  shouldComponentUpdate(nextProps,nextState){
    return! (nextState.car ===this.state.car)
  }
Copy the code

Solution 2

import React from 'react'Change react.componentto react.pureComponentclass Parent extends React.PureComponentNotes //PureComponentThe bottom layer decidesobj = = =thisThe state?const obj = this.state // point to the same address
obj.car = maybach
this.setState(obj)  // The underlying PureComponent will say obj === this.state?So this is going to fail because obj andthisThe address of state is the same as that of renderthis.setState({
	car: maybach}) -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- such as a stus in the stateconst {stus} = this.state  // point to the same address
stus.unshift('xiao li')
this.setState({stus:stus}) so this way will modify failed addresses that are the same as PureComponent the underlying layer will judge the same will not render like thisconst {suts} = this.state
this.setState({stus: ['xiao li'. stus]})// You can also use arrays, shallow copies of objectsNewArr = [...arr] newObj =JSON.parse(JSONAbout stringify (obj))JSON.parse(JSON.stringify(obj)) implements some deep copy pitshttps://segmentfault.com/a/1190000020297508?utm_source=tag-newest
Copy the code

RenderProps slot

In addition to the traditional father putting A and B in A, there is another form of father and child

The array that childrenProps B needs for A is not received

class Parent extends React.PureComponent {
  render() {
    return (
      <div>
        <h1>I'm the parent component</h1>
        <A>{/* if a is the props of b, b will be the children of a */<B></B> 
        </A>
      </div>)}}class A extends React.PureComponent {
  render() {
    return (
      <div>
        <h3>I'm A child of A</h3>{this.props. Children} {/* Get the children of props */}</div>)}}class B extends React.PureComponent { render() { return <h3>I'm a child of B</h3>}}Copy the code

RenderProps, dynamically passing content destructions inside components (tags)

class Parent extends React.PureComponent {
  render() {
    return (
      <div>
        <h1>I'm the parent component</h1>
        <A render={()= > <B />} ></A>{/* Pass a callback function to a */}</div>)}}class A extends React.PureComponent {
  render() {
    return (
      <div>
        <h3>I'm A child of A</h3>{this.props. Render ()} {/* props.</div>)}}class B extends React.PureComponent { render() { return <h3>I'm a child of B</h3>}}Copy the code

Callback function data transmission value

// Class components
class Parent extends React.PureComponent {
  render() {
    return (
      <div>
        <h1>I'm the parent component</h1>
        <A render={(name)= > <B name={name} />} ></A>{/*2. This parameter receives assignment to B*/}</div>)}}class A extends React.PureComponent {
  render() {
    return (
      <div>
        <h3>I'm A child of A</h3>{this.props.render(this.state.name)} {/*1. The value passed here */}</div>
    )
  }
  state = { name: 'tom'}}class B extends React.PureComponent { render() { console.log(this.props.name); return <h3>I'm a child of B</h3>}} is equal to a {this.props.render(this.state.name)} <A render={() = > <Some/>} / >Copy the code

Error Boundary

Only errors generated during the life cycle of a descendant component are caught, not errors generated by its own component and compositing events generated by other components. Error bounds generated in timers should be manipulated in the parent component of the error-prone component

// If any child component reports an error, the call is triggered with an error message
static getDerivedStateFromError(err){}
// An error occurred with the neutron component during rendering
compomentDidCatch(){}




// Class components
class Parent extends React.PureComponent {
  render() {
    return (
      <div>
        <h1>I'm the parent component</h1>
        {this.state.hasError ? <h2>Page fault</h2> : <A />}
      </div>
    )
  }
  state = {
    hasError: ' ' // Identifies whether the child component has an error
  }
  // If any child component reports an error, the call is triggered with an error message
  static getDerivedStateFromError(err) {
    console.log('err', err);
    return { hasError: err }
  }
}


class A extends React.PureComponent {
  render() {
    return (
      <div>
        <h3>I'm A child of A</h3>{this.state.name.map((item) => {// This is an error because the status does not return anything<h1>item</h1>
        })}
      </div>)}}Copy the code

Summary of component communication modes

Relationships between components

  1. Father and son
  2. Brothers (non-nested components)
  3. Grandparent (Cross-level components)
Communication mode1. props
	children props
	render props
2.Message subscription publishing pubs-sub, etc3.Centralized management of REDUx, DVA, etc4.Context producer-consumer patternCopy the code

A better way to match

Parent component: props Sibling component: message subscription Grandchild (cross level) : message subscription, centralized, Context (less for development, more for packaging plug-ins)Copy the code