1. Introduction

1.1 Learning Background

The author uses Vue as his technical stack and has nothing to do in his spare time. I would like to review the basic course of React and record my own learning process of React, hoping to help beginners like me. Here is the link of The course of React: React16 free video tutorial (28 episodes in total).

1.2 introduction of the React

Currently, the most popular front-end framework in the world is launched and maintained by Facebook with a strong community. Most of the first and second tier Internet companies in China use React for development, and some useful frameworks such as ReactNative and React VR have been derived.

React development environment (React 17)

2.1 the Node. Js installed

Go to nodeChinese: nodejs.cn/ and install the stable version. After installing the stable version, use win+R to open CMD and enter the code

node -v
Copy the code

If the correct version number is displayed, the Node is successfully installed. Then check the NPM status

npm -v
Copy the code

If the correct version number appears, NPM is fine

2.2 React Scaffolding Installation

As a beginner, use create-React-app, the official scaffolding tool recommended for installation, to reduce potholes

npm install -g create-react-app
Copy the code

2.3 Creating a React Project

After the scaffolding is installed, create a ReactDemo folder on drive D, then go to the folder and create the React project

D: // create ReactDemo folder creation-react-app myreact // create ReactDemo folder creation-react-app myreact // create ReactDemo folder creation-react-app myreact // create ReactDemo folder creation-react-app myreact // Enter the project directory NPM start // preview the project. If the project can be opened normally, it indicates that the project is created successfullyCopy the code

3. Introduction of scaffold generation project directory

/ / table of contents├─public │ ├─ favicon. Ico │ index.html │ manifest.json │ robots. TXT │ ├─ SRC app.css app.js App.test.js index.css index.js logo.svg reportWebvitals.js setuptests.js │ gitignore │ package-lock.json │ package.json │ README, mdCopy the code

3.1 Project root directory file

  • Public: a public file that stores public templates and ICONS.
  • SRC: Stores the main project code as well as some project static resources, encapsulated apis, and so on.
  • gitignoreThis is git’s optional upload configuration file, usually scaffolding is already configured with some files that do not need to be uploaded, such asnode_modules,buildAnd so on.
  • package-lock.jsonThis file locks the version number at the time of installation, and needs to be uploaded to Git to ensure that others will not use git againnpm installWhen everyone’s dependence can ensure consistency.
  • package.json: This file iswebpackConfiguration and project package management file, usually NPM installed some package version will be recorded in it, whichdependenciesThe packages inside are the ones that will continue to be used after the project goes live,devDependenciesThe package inside is used by the development environment, online will not be used.
  • README.md: This file is mainly used to record the contents of the project, mainly usedMarkdownSyntax to write

3.2 Public Folder

  • Favicon. ico: This is the TAB icon of the project in the browser, usually displayed in the upper left corner of the browser TAB.
  • index.htmlThe react code we wrote is embedded in the template file on the first pagebodyThe followingrootdivThe inside.
  • Mainifest. Json: mobile configuration file.

3.3 SRC Folder

  • Index.js: entry file for the project
  • app.jsThe scaffolding is configured for us as the first modulenpm run startThen open the web page to see the first page
  • Serviceworker.js: This file is used to write mobile applications. PWA must use this file, which is equivalent to offline browsing.

3.4 Processing before writing code

Ico and index.html file. Delete the rest. Delete this line of code inside index.html

<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
Copy the code

SRC folder only app.js and index.js, inside the code processing is as follows

//App.js
function App() {
  return <div>Initialize the</div>;
}

export default App;
Copy the code
//index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>.document.getElementById('root'));Copy the code

Then open the page and see only the white background text initialization means that our project is initialized.

4. HelloWorld

4.1 app. Js code

import React, { Component } from 'react';

class App extends Component {
  render() {
    return <div>Hellow World</div>; }}export default App;
Copy the code

The first step here is to introduce the Component from the React core library

import React, { Component } from 'react';
Copy the code

This is ES6’s deconstruction assignment method

import React from 'react';
const Component = React.Component;
Copy the code

4.2 JSX grammar

JSX is a combination of Javascript and XML. React invented JSX, which makes it easy to create a virtual DOM using HTML syntax. When encountered with <, JSX interprets it as HTML and when encountered with {it interprets it as JavaScript.

// JSX syntax compared to normal JS syntax
//jsx
<ul className="my-list">
  <li>JSPang.com</li>
  <li>I love React</li>
</ul>;
// Plain JS syntax
var child1 = React.createElement('li'.null.'JSPang.com');
var child2 = React.createElement('li'.null.'I love React');
var root = React.createElement('ul', { className: 'my-list' }, child1, child2);
Copy the code

As can be seen from the above comparison, there is no difference between using JSX syntax in JS and writing in HTML at ordinary times, while writing HTML structure code in JS with ordinary JS syntax is complicated, the appearance of JSX greatly reduces our code quantity

Another advantage of JSX syntax is that variables can be enclosed in {} and rendered in a page, for example

class App extends Component {
  render() {
    const num = 10;
    return (
      <ul className="my-list">
        <li>{num}</li>// The ternary operator can also be used within {}<li>{false ? 'Red' : 'blue '}</li>
      </ul>); }}Copy the code

4.3 VSCode configuration

Using JSX syntax in js does not recognize and generate labels quickly. If you also use VSCode, you can add this line of code to your Settings

"emmet.includeLanguages": {
  // JSX code prompt
  "javascript": "javascriptreact"
},
Copy the code

5. React Instance – Little Sister Service menu

5.1 Creating the Little Sister Component

In the SRC folder, create a new folder called Xiaojiejie. Inside the folder, create an index.js file and write a basic structure

import React, { Component } from 'react';

class Xiaojiejie extends Component {
  render() {
    return (
      <div>
        <div>
          <input type="text" />
          <button>Increase the service</button>
        </div>
        <ul>
          <li>The head massage</li>
          <li>Essential oil TuiBei</li>
        </ul>
      </div>); }}export default Xiaojiejie;
Copy the code

After building the basic structure, we went to app.js to introduce the little sister component

import React, { Component, Fragment } from 'react';
//import imports the little sister component. Note that the component name and use must be uppercase
import Xiaojiejie from './Xiaojiejie';
class App extends Component {
  render() {
    return (
      <Fragment>
        <div>Hello World</div>{/* Use the little sister component */}<Xiaojiejie />
      </Fragment>); }}export default App;
Copy the code

After introducing the little sister component, we will open the page to see if the structure is displayed, which means that this step is successful.

5.2 Rules for Component Wrapping &Fragment tag & Comments in JSX

  • The Fragment rule: This is a very important rule. For example, in the code above, we will get an error if we remove the outer

    . React requires that a component be wrapped at the outer layer.

    // The outermost tag is missing. Only one tag can exist in the outermost tag of the return
    class App extends Component {
      render() {
        return (
          <div>Hello World</div>
            {/* Use the little sister component */} <Xiaojiejie /> ); }}Copy the code
  • Fragment tags: Most of the time you can solve component wrapping problems by adding a div to the top layer, but sometimes, like flex layout, if you have a div wrapped around the top layer, the inside will not work. In this case, use the Fragment tag, which wraps the tag without showing it on the page.

    // Need to be introduced before use
    import React, { Component, Fragment } from 'react';
    Copy the code
  • JSX internal comments: Normal JS comments only need //, but in JSX, you need to wrap the comments with {/**/}, or you can use the editor’s CTRL +/ shortcut comment

6. Add features to the Little Sister service

6.1 Reactive Data Binding

React uses the virtual DOM, so it is not recommended to operate DOM elements directly. Therefore, try to use data-driven methods to do so. React will update DOM based on data changes.

We first need to bind the values to the input and implement data responsiveness. We define the data first

class Xiaojiejie extends Component {
  // Use the constructor
  constructor() {
    super(a)// Call the parent constructor, fixed
    this.state = {
      /** New service content */
      serviceValue: ' './** Service list */
      serviceList: []}}... }Copy the code

After defining the data, bind it to the input

// Use {} to store variables
<input value={this.state.serviceValue} type="text" />
Copy the code

After doing this, we can change the value of serviceValue from constructor and see that the input field on the page is already displaying the data properly. One problem is that the input field does not change.

This is caused by forcing the binding of value. To change the value we need to unbind the response event and dynamically change the value of serviceValue

/ / dom code
<input value={this.state.serviceValue} onChange={this.serviceChange} type='text' />
// Create a serviceChange event
class Xiaojiejie extends Component {
  constructor(){... }render() {
    return (
    ...
    );
  }
  // Create a serviceChange event, the same as render
  serviceChange = (e) = > {
  	console.log(e.target.value);
    this.state.inputValue=e.target.value
  }
}
Copy the code

After the event is created and bound, we will go to the browser and try to enter the value in the input field. We will find that the debugger reported an error because the data in the state field cannot be changed directly. Instead, we will use setState() to change the value

/ / dom code
<input value={this.state.serviceValue} onChange={this.serviceChange} type='text' />
// Create a serviceChange event
class Xiaojiejie extends Component {
  constructor(){... }render() {
    return (
    ...
    );
  }
  // Create a serviceChange event, the same as render
  serviceChange = (e) = > {
  	console.log(e.target.value);
  	this.setState({
        serviceValue:e.target.value
    })
  }
}
Copy the code

Now that you can see the correct result on the console, there are three ways to write React events and bindings

6.2 Three Methods for Creating events and Binding

// The first way is to change the direction of this by using bind, otherwise an error will be reported
<input value={this.state.serviceValue} onChange={this.serviceChange.bind(this)} type='text' />
serviceChange(e){
  	this.setState({
        serviceValue:e.target.value
  })
}
// The second way, I prefer to use
<input value={this.state.serviceValue} onChange={this.serviceChange} type='text' />
// By using the arrow function when creating the method, the this keyword points to this at the position defined by the arrow function.
serviceChange = (e) = > {
  	this.setState({
        serviceValue:e.target.value
  	})
}
// The third way of doing this is by changing the direction of this from constructor
constructor(props){
    super(props)
    this.serviceChange=this.serviceChange.bind(this)}render() {
    return (
       <input value={this.state.serviceValue} onChange={this.serviceChange} type='text' />
     );
}
serviceChange(){
  	console.log(this.props.index)
}
Copy the code

6.3 Adding Service Functions

After the data responsive binding, we can start to implement the add service function. First we need to rewrite the contents of

    into the data rendering structure
<ul>
  {this.state.serviceList.map((item, index) = > {
    React generates an error when a key is missing
    return <li key={index}>{item}</li>;
  })}
</ul>
Copy the code

Bind click events to buttons

<button onClick={this.addservice}> addService </button>Copy the code

Then create the Add service event

addService = (e) = > {
  this.setState({
    serviceList: [...this.state.serviceList, this.state.serviceValue],
  });
};
Copy the code

Note that setState() cannot use the array method push(), because push() does not return a value, resulting in the corresponding key value changing to number

// Error
addService = (e) = > {
  this.setState({
    serviceList: this.state.serviceList.push(this.state.serviceValue),
  });
};
// You can use concat instead
addService = (e) = > {
  this.setState({
    serviceList: this.state.serviceList.concat(this.state.serviceValue),
  });
};
Copy the code

6.4 Deleting a Service

First we need to bind

  • to the click event, and we need to get the current index at click time
  • <ul>
      {this.state.serviceList.map((item, index) = > {
        return (
          <li key={index} onClick={this.deleteService.bind(this, index)} >
            {item}
          </li>
        );
      })}
    </ul>
    Copy the code

    Bind (this, xx); if you write Fn(xx), it will become a direct call

    Then we create the delete event

    // Delete the service
    deleteService = (index) = > {
      React forbids direct manipulation of state, so we create a new variable to operate on
      let list = this.state.serviceList;
      list.splice(index, 1);
      this.setState({
        serviceList: list,
      });
    };
    Copy the code

    This is the end of the little project.

    7. Component splitting

    Although the above small project has been completed, in the actual work, we must carry out component splitting, which is conducive to our later maintenance.

    Start by listing the entire code, noting where you need to split it

    import React, { Component } from 'react';
    
    class Xiaojiejie extends Component {
      constructor() {
        super(a);// Call the parent constructor, fixed
        this.state = {
          /** New service content */
          serviceValue: ' './** Service list */
          serviceList: ['Head massage'.'Essential oil push back']}; }render() {
        return (
          <div>
            <div>
              <input
                value={this.state.serviceValue}
                onChange={this.serviceChange}
                type="text"
              />
              <button onClick={this.addService}>Increase the service</button>
            </div>Split {/ * * /}<ul>
              {this.state.serviceList.map((item, index) => {
                return (
                  <li key={index} onClick={this.deleteService.bind(this, index)} >
                    {item}
                  </li>
                );
              })}
            </ul>
          </div>
        );
      }
      // Reactive data binding
      serviceChange = (e) = > {
        this.setState({
          serviceValue: e.target.value,
        });
      };
      // Add services
      addService = () = > {
        this.setState({
          serviceList: this.state.serviceList.concat(this.state.serviceValue),
        });
      };
      // Delete the service
      deleteService = (index) = > {
        let list = this.state.serviceList;
        list.splice(index, 1);
        this.setState({
          serviceList: list,
        });
      };
    }
    
    export default Xiaojiejie;
    Copy the code

    7.1 Creating a Service List Component

    Under the Xiaojiejie folder, create a new xiaojiejiejieitem.js and write the infrastructure

    import React, { Component } from 'react';
    
    class XiaojiejieItem extends Component {
      render() {
        return <li>Service List module</li>; }}export default XiaojiejieItem;
    Copy the code

    7.2 Value Transfer of Parent and Child Components

    Our requirement is functional modularity. Once the service list component is removed, we need to introduce sub-components, and then pass the service list parameters to the sub-components to make them visible

    The father the son

    Parent component writing

    // Introduce the child components first
    import XiaojiejieItem from './XiaojiejieItem';
    // Using the subcomponent, pass the parameters to the subcomponent, similar to vUE: custom attribute name = value format, subcomponent replaces the previous li tag, also need to set the key value
    <ul>
      {this.state.serviceList.map((item, index) => {
        return <XiaojiejieItem key={index} content={item} />;
      })}
    </ul>;
    Copy the code

    Subcomponent writing

    // accept this as this.props. Xx
    class XiaojiejieItem extends Component {
      render() {
        return <li>{this.props.content}</li>; }}Copy the code

    The page should display normally, but we found that there is still a deletion service function missing, which requires the child component to pass the index to the parent component and then call the parent component’s method to delete it

    Child the parent

    Parent component writing

    // Pass the index and the method to delete the service to the child component
    <ul>
      {this.state.serviceList.map((item, index) = > {
        return (
          <XiaojiejieItem
            key={index}
            content={item}
            index={index}
            deleteService={this.deleteService}
          />
        );
      })}
    </ul>
    Copy the code

    Subcomponent writing

    // Bind the click event to Li
    class XiaojiejieItem extends Component {
      render() {
        return <li onClick={this.handleServiceList}>{this.props.content}</li>;
      }
      // Pass the index to call the parent component method
      handleServiceList = () = > {
        this.props.deleteService(this.props.index);
      };
    }
    Copy the code

    8. Simple application of PropTypes

    8.1 role

    Verify the validity of the incoming data, and the JavaScript console throws a warning when invalid data is passed to the props. For performance reasons, propTypes are validated only in the development environment.

    8.2 Simple Use

    In xiaojiejieitem.js first introduced

    import PropTypes from 'prop-types';
    Copy the code

    Then go and set the types of the different parameters, note that they are written outside the class

    // propTypes here start with lower case
    XiaojiejieItem.propTypes = {
      content: PropTypes.string,
      deleteService: PropTypes.func,
      index: PropTypes.number,
      // Set a non-required parameter and add the keyword isRequired so that no error will be reported if the value is not passed
      name: PropTypes.string.isRequired,
    };
    Copy the code

    After setting the type of the parameter, an error will be reported on the console if the parameter passed by the parent component does not match the type we defined

    React Lifecycle

    9.1 Four major stages

    The React lifecycle can be divided into four major phases:

    • Initialization: Initialization phase
    • Mounting: Mount phase
    • Updation: Component update phase
    • Unmounting: Destruction stage

    9.2 Each life cycle and its usage

    1. Mount and uninstall process
    • componentWillMount(): is called before a component renders. It is rarely used, but more often used during server-side rendering. It represents the process that the React 17 version is about to be abandoned when the component has undergone a constructor() initialization of the data, but has not rendered the DOM.
    • componentDidMount()When the component is rendered for the first time, the DOM node has been generated. Ajax requests can be made here, and the component will be rendered again after the setState data is returned.
    • componentWillUnmount(): is called immediately before the component is removed from the DOM, usually for destructionsetTimeout, setIntervalAs well asremoveEventListener.
    2. Update process
    • getDerivedStateFromProps(nextProps, prevState): is called before the Render method is called, and is called both during the initial mount and during subsequent updates. It should return an object to update state, if returnednullNothing is updated.
    • shouldComponentUpdate(nextProps,nextState): Controls whether the component is updated by returning a Boolean valuePerformance optimization.Because rerendering the React parent causes all child components to rerender as well, so you need to make a judgment in this life cycle of the child component.
    • getSnapshotBeforeUpdate(prevProps, prevState): called before the last render output (committed to the DOM node). It enables the component to capture some information from the DOM before changes are made. Any return value from this life cycle is passed as a parameter tocomponentDidUpdate().
    • componentDidUpdate(prevProps,prevState)React will only enter componentDidmount after the first successful initialization of the component after it has been updated, and will enter this life cycle after every re-rendering.
    • render(): The Render function inserts the DOM structure generated by JSX. React generates a virtual DOM tree. At each component update, react uses its diff algorithm to compare the old and new DOM trees before and after the update. And re-render.
    • getDerivedStateFromError(): This life cycle is invoked after a descendant component throws an error. It takes the thrown error as an argument and returns a value to update state

    Refer to the article

    • React16 Free Video Tutorial (28 episodes)
    • React lifecycle
    • React 英 文 版