React Fast Violence Introduction

React is one of the three frameworks now. After a short period of learning, I sorted out some notes and shared them: If there are mistakes, please point them out.

1. React

1. What is React?

React is a Javascript library developed by Facebook for building user interfaces. Compared with Vue, React’s grammar is simple and easy to use, which is suitable for small and refined projects. However, React is better than Vue in the reusability and designability of components, which is suitable for large projects. React separates and asseminates pages in the form of component by component, and reuse to improve efficiency (see the figure below) React’s data processing and management is more clear than native data.

2. How do you React

  1. Declarative Design – Each component of React is created declaratively, making the page logic clearer

2. Virtual DOM−React creates a virtual DOM each time it renders a page, and compares it with the existing DOM. If there is a difference, it will replace and re-render it, improving efficiency. 3. JSX − JSXJavaScriptExtensions of syntax.ReactDevelopment does not necessarily useJSX, but we recommend using it.

// Create the element in javascript
const DOM = document.createElement("h1"); / / true DOM
DOM.innerText = "This is the h1 tag.";

// Create elements in JSX
const VDOM = <h1>This is the H1 tag</h1> / / virtual DOM
Copy the code
  1. Components — Building components with React makes code more reusable and can be used in large projects.
// Each component needs to be declared before it can be used
import React, {PureCompoent} from "react";
export default class Header extends PureCompoent{
    render(){
        return <header>This is the header component</header>}}// ------------------------------------------------
// Call the header component when it needs to be used
import Header from "./Header";
<Header></Header>
Copy the code
  1. Unidirectional response data flow − React implements unidirectional response data flow, which reduces duplication of code, which is why it is simpler than traditional data binding. (More on this later)

3. Installation and use

  1. Use the CDN
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
Copy the code
  1. Import the React package by downloading it
<script src=".. /js/react.development.js"></script>
<script src=".. /js/react-dom.development.js"></script>
<script src=".. /js/babel.min.js"></script>
Copy the code
  1. Use the React scaffoldingcreate-react-appCreating project files will come with react
NPM I create-react-app-g create-react-app Project nameCopy the code

ReactDOM is independent of react (to prevent react from being too big and overgrown).

4. Virtual DOM

(1) About the virtual DOM

The virtual DOM is essentially an object, and the real DOM is also an object, but the virtual DOM has fewer properties and is more lightweight.

/ / virtual DOM
const VDOM = <h1>Hello World</h1>// There is no need for quotation marks because it is not a string
/ / true DOM
const TDOM = document.querySelector("#app");

console.log("Virtual DOM:", VDOM);   // Object
console.log("Real DOM:", TDOM);   // <div id="app"></div>
console.log("Virtual DOM type:".typeof VDOM);  // object
console.log("Real DOM type:".typeof TDOM);  // object
console.log(VDOM instanceof Object);    // true
console.log(TDOM instanceof Object);    // true
Copy the code

The virtual DOM will eventually be converted by React into a real DOM for rendering on the page

(2) Create the virtual DOM

  1. throughReactThe method ofcreateElement()Method to create the virtual DOM
// React. CreateElement (tag name, tag attribute, tag content)
const VDOM1 = React.createElement("h1", {id: "title"}, "This is Title");
Copy the code
  1. Create a virtual DOM using the syntax sugar of Method 1
const VDOM2 = <h1 id="title">This is Title</h1>;
Copy the code

About 5.JSX

JSX syntax is very similar to javascript syntax, with a few caveats

/ / virtual DOM
const VDOM = (  // The JSX tag is enclosed in parentheses to represent the hierarchy.
    <h1>
        <span>Hello World</span>
    </h1>
)
const myid = "HeLlO";
const content = "Happy New Year"
const students = [
{id: "001".name: "Tom".age: 18},
{id: "002".name: "Tim".age: 19},
{id: "003".name: "Jerry".age: 20},];const VDOM2 = (
    <div>
        <h2 className="title" id={myid.toLowerCase()}>
            <span style={{color: 'pink'}} >{content}</span>
        </h2>
        <ul>{/* Use ES6's map() function to render the list (to batch render the data onto the page) */} {students.map(student=>{return<li key={student.id}>{student.name}---{student.age}</li>}}</ul>
        <input type="text"/>    
    </div>
)
Copy the code

JSX syntax rules:

  1. Do not use quotation marks when defining the virtual DOM
  2. Used when a TAG is mixed with a JS expression{}
    • The expression produces a value that can be placed wherever the value is needed
    • Statement is a string of code used to process logic
  3. The class name in the tag specifies not class, but className
  4. When using inline styles in tags, use double parentheses (use small humps for CSS styles)
  5. When adding event attributes, such asonclick),onCapitalize the first letter of the following words (e.gonClick)
  6. The virtual DOM must have only one root tag
  7. Label must be closed
  8. Label the beginning
    • Tags that start with lowercase are compiled by JSX as HTML tags, and an error is reported if there is no CORRESPONDING HTML element with the same name
    • If the label starts with uppercase, JSX recognizes it as a component. If no corresponding component is found, JSX recognizes it as a component

6. Render to the page

Use ReactDOM’s render() method for rendering

const VDOM = <h1 id="title">This is a Title</h1>;    // Create the virtual DOM
// reactdom.render (component (virtual DOM), which element to bind to);
ReactDOM.render(VDOM, document.querySelector("#root"));
Copy the code

Two, the use of components

In React, there are two ways to create components: functional components and class-based components. Among them, class-based components are frequently used (after React 16.8 appeared Hook, functional components also became more frequent).

Functional component

As the name suggests, this component is written by a function

function Demo(props){    // Define a component called Demo
    return <h2>This is a component</h2>;    // Return the DOM contents of the component
}
ReactDOM.render(<Demo/>.document.querySelector("#root"))
Copy the code

Functional component definitions:

  • Function names must be capitalized
  • When called, it is called as a label and begins with an uppercase
  • The parameters of a functional component areprops(More on that later)

The component class type

The Component is built from a class, but inherits from a Component class that comes with React.

// Create class-like components using ES6 writing and inherit from react.ponent
class Demo extends React.Component{
    
    // Add the render() function (mandatory) that returns the component's virtual DOM
    render(){
        console.log(this);      // This of the render() function points to the instance object of the component
        return <h1>This is a Title!</h1>
    }
}
ReactDOM.render(<Demo/>.document.querySelector("#root"));
Copy the code

Class component definition:

  • Must inheritReactBuilt-in classComponent
  • Must include methodsrender()
  • The constructorconstructor()The parameters forprops(more on this later), if necessaryconstructorThe constructor of the superclass must be calledsuper(props)

Execution of class component when mounted:

  1. ReactParsed component label, foundDemocomponent
  2. Found as a class component, and thennewOut of the class instance object, through the instance call on the prototype objectrendermethods
  3. willrenderMethod returned byVirtual DOMtoReal DOMAnd then render it to the page

Component definition considerations:

  1. Of a class componentrender()There must be one component label returned and one component label returned by functional componentsRoot tag
  2. Must begin with a capital letter

Mounting and unmounting components

We have seen many mounts, so go straight to the code:

// reactdom.render (component, which element to bind to);
ReactDOM.render( <Demo/>.document.querySelector("#app"));Copy the code

Uninstall the code is longer, I also put directly:

/ / ReactDOM. UnmountComponentAtNode (to uninstall components on which element);
ReactDOM.unmountComponentAtNode( document.querySelector("#app"));Copy the code

Other tips

  1. The components that contain form elements are divided intoUncontrolled rentwithThe controlled components
    • Controlled component: The input component of the form component follows the input and stores the content in the state (updated at any time)
    • Uncontrolled components: Input components to form components the contents of the components are stored in state only when required (ready-to-use)

Three properties of a component

The essence of a component is an object, and objects naturally have properties. The three most commonly used properties in components are state, props, and refs

1. state

State is the state of a component, or more specifically, the data that the component stores (and uses)

Use in class-like components:

class Weather extends React.Component{
    constructor(props){
        super(props);
        // this.state = {weather: "Spring"} // You can define state in the constructor
    }
    
    state = {   / / define the state
        weather: "summer",}render(){
        // The current season is summer
        return <h2>Current season: {this.state.weather}</h2>}}Copy the code

State is defined by calling the value class component in this. State:

  • Can be initialized in the constructorstate
  • You can add attributes to a classstateTo initialize the

In functional components

  • inReact16.8Previously, functional components could not have their ownstate(Because the data will be initialized repeatedly)
  • toReact16.8After, appearedHookMethod so that functional components can also be usedstateFeatures, you can understand first, later will teach.
function Demo(){
    const [weather, setWeather] = React.useState("Winter");
    return <h2>Current season: {weather}</h2>     // The current season is: Winter
}
Copy the code

Change the state

In functions of class-like components, you’ll find direct changes to the value of state, such as:

this.state.count = 1
Copy the code

If you use the count value in the page, you’ll see, why is the page not changing? Which function does the page render depend on? Don’t you rely on the render() function? Wouldn’t it be too much trouble if you called render() every time you changed state directly? It’s not recommended in React either. It’s not allowed to change state directly. Instead, it’s done in a specific way, using the setState() method on the prototype object of the class.

setState()
this.setState(partialState, [callback]);
Copy the code
  • partialState: Part of the object’s state to be updated
  • callback: callback function after updating the state

There are two ways to write setState:

this.setState({
    count: 1,})Copy the code

Method 2:

// Pass a function that returns the object x needs to be changed to, taking the current state
this.setState(state= > ({count: state.count+1});
Copy the code

Which writing to use depends on whether the modified state needs to be applied to the current state

forceUpdate()

Another way to change the status is called forceUpdate, which means to force an update. Parameter is the callback function after the update state is complete

this.forceUpdate([callback]);
Copy the code

setStateUpdate andforceUpdateUpdates are a merge operation, not a replacement operation


  • In the implementationsetStateAfter the operation,ReactIt will automatically call it for usrender()
  • render()Is the number of times1+n(1 is the automatic call during initialization, n is the number of status updates (i.esetStateorforceUpdateThe number of times
  • Use as little or no as possibleforceUpdate

2. props

Unlike state, which is the component’s own state (data), props is the state (data) that was passed to it from outside

propsIf a modification is made within a component, it must be made by the person who passed it in

Class component

class Person extends React.component{

    constructor(props){     // Remember that the constructor argument can also get props
        super(props);
    }

    // Props can be restricted using the static attribute propTyps
    static propTypes = {
         // Before version 16, use the React PropTypess property to pass values
        // name: React.PropTypes.string.isRequired,
        
        // After version 16, PropTypes were removed separately from React as a separate entity and needed to be imported separately
        name: PropTypes.string.isRequired, // It is a string, and a value must be passed
        sex: PropTypes.string,  // The value is a string
        age: PropTypes.number,  // Numeric type
        speak: PropTypes.func,  // Function type
    }
    
    // You can use the static property defaultProps to set the default values for some prop
    static defaultProps = {
        sex: "Male".// Set prop to 'male' by default
    }

    render(){
        const {name, sex, age} = this.props;    // Get the value from props
        return (
            <ul>
                <li>Name: {name}}</li>
                <li>Gender: {sex}</li>
                <li>Age: {age}</li>
            </ul>)}}// reactdom. render(
      , document.queryselector ("#root")); // Passes the props value as an attribute

ReactDOM.render(<Person {. p} / >.document.querySelector("#root"));// We can use the extension operator to pass props
Copy the code

We can use this. Props to get the props of a valued component:

  1. By passing the value on the component label, you get the passed value in the component
  2. Can be obtained in the constructor argumentsprops
  3. You can set them separatelypropTypesdefaultPropsTwo properties to operate separatelypropsSpecification and default values, both of which are added directly to class-like componentsA prototype objectSo it needs to be addedstatic)

Functional components

Remember what the parameters of a functional component are? Is the props. This is passed in the same way as for class-based components, by passing values in the component label

function Person(props){   // The parameter is props
    const {name, sex, age} = props;     // Use the placeholder to get the props value
    return (
        <ul>
            <li>Name: {name}}</li>
            <li>Gender: {sex}</li>
            <li>Age: {age}</li>
        </ul>
    )
}

Person.defaultProps = {     // Set props by default
    sex"Male".age18,
}
Person.propTypes = {    // Set props limit
    name: PropTypes.string.isRequired,
    sex: PropTypes.string,
    age: PropTypes.number,
}

const p = {name:"Jerry".sex:"Female".age:16}
ReactDOM.render(<Person {. p} / >.document.querySelector("#app"));
Copy the code

Function component props

  1. It is also passed in the component labelpropsThe value of the
  2. The parameters of the component function areprops
  3. rightpropsThe limits and defaults set for the prototype are also set for the prototype object

3. refs

Suppose you have a form element in your component, and you need to get its value. How do you get it? Some people might want to use document.querySelector to find the element after giving it its binding ID, but this would go against React’s idea and start working with DOM elements again. All React provides is a third feature, refs

In the history of React, there are three methods to operate REFS, which are:

  • String form
  • The callback form
  • createRefIn the form of

Let’s take a look:

Class componentrefs

(1) In the form of stringrefs
class Demo extends React.Component{
    
    showData(){
         // Get the element from the specified refs name
        const {myInput} = this.refs;   // Return the element
        alert(myInput.value)
    }
    
    render(){
        return (
            <div>{/* bind this input tag to the ref property */}<input type="text" ref="myInput" placeholder="search something" />{/* Event binding is covered below */}<button onClick={this.showData}>Show Data</button>
            </div>)}}Copy the code
(2) in the form of callbackrefs

It’s pretty simple, but in a later release, officials decided it was a problem, so they released a completely new version: using callback functions to manipulate refs

class Demo extends React.Component{
    
    showData(){
        const {myInput} = this;   // Return the element
        alert(myInput.value)
    }
    render(){
        return (
            <div>{/* The callback takes the element itself, which is bound to this by the function */}<input type="text" ref={ e= > this.myInput = e } placeholder="search something" />
                <button onClick={this.showData}>Show Data</button>
            </div>)}}Copy the code
(3) createRef form (recommended)

The React method createRef() was introduced as a new way to use refs, as the React method createRef() was introduced.

class Demo extends React.Component{

    // Create an ref container using react.createref ()
    myRef = React.createRef();

    showData = () = >{
        // Get the DOM element from the container
        const {current} = this.myRef;
        alter(current.value);
    }

    render(){
        return (
            <div>{/* bind the DOM element to the container */}<input ref={this.myRef} placeholder="Click prompt data" type="text"/>
                <button onClick={this.showData}>ShowData</button>    
            </div>)}}Copy the code

Note: a ref container can only store one element (dedicated), and the one added later pushes out the previous one

Functional componentsrefs

  • inReact16.8Before, andstateSimilarly, functional components cannot be usedrefsfeatures
  • inReact16.8After, appearedHookFunction, enabling the use of functional componentsrefsCapability of a feature

The following code at this stage do not need to understand first, understand.

function Demo({
    const [count, setCount] = React.useState(0);
    function add(){
        setCount(count= > count+1);
    }
    return (
        <div>
            <h2>Current sum: {count}</h2>
            <button onClick={add}>Click on add a</button>
        </div>)}Copy the code

Event binding for components

1. Bind events in functional components

You can define another function (a built-in function) within the function and then call it

function Demo(props){
    function showData(){
        console.log(props);
        alert("Triggered the event.");
    }
    return (
        <div>
            <button onClick={showData}>Click on the trigger</button>
        </div>)}Copy the code

2. Bind events to class-based components

It can be called from within a class-like component through the methods of the class itself

class Demo extends React.Component{
    state = { count: 0 }    / / define the state
    showData(){
        alert("Triggered the event.")
        console.log(this.state.count);; An error}render(){
        return (
            <div>
                <button onClick={this.showData}></button>
            </div>
        )
        // Popup successfully, but output error}}Copy the code

Here you will find, although successfulalter, but the outputstateIt’s an error. Why is that?

When you use this.state in a component, this refers to the class’s prototype object, the class itself. This is undefined in the function body, and there is no state in the prototype object. There are two solutions:

  • usebind,applyAnd so onthisPoint to the
  • useArrow functionChange,thisPoint to (recommend)
class Demo extends React.Component{
    constractor(props){
        super(props);
        // this.showData = this.showData.bind(this); 1 / / method
    }
    
    state = { count: 0 }    / / define the state
    showData = () = >{    2 / / method
        alert("Triggered the event.")
        console.log(this.state.count);; An error}render(){
        return (
            <div>
                <button onClick={this.showData}></button>
            </div>
        )
        // Popup successfully, but output error}}Copy the code

3. React event handling

  • throughonXxxProperty to specify the event handler (note case
    • React uses custom (synthesized) events instead of native DOM events (for better compatibility)

    • React events are handled via event delegate (delegated to the outermost element of the component) (for efficiency)

    • The DOM element object can be obtained through the event. Target of the event to minimize the use of refs

    • Do not bind events with parentheses; this is recognized by JSX as an execution function

    • Note the pointing of this when binding functions in class-like components (it is recommended that all functions bind with arrows)

Component life cycle

Those familiar with Vue should be familiar with the life cycle. A lot of things happen when a component is mounted to the page, and the lifecycle can be thought of as the process of execution of a component. We can do some operations in a process node, and this is the lifecycle hook (function). Lifecycle functions are only applicable to class-based components, not functional components, but hooks after React16.8 allow functional components to implement functionality similar to lifecycle hooks

1. Before React 16

Here’s the process:

  • Mount its own component
    1. constructor: constructor (initialization)
    2. componentWillMount: Before the component is mounted
    3. render: The component is being mounted
    4. componentDidMount: After the component is mounted
  • Owning a parent component and updating its state (setState) :
    1. The parent componentshouldComponentUpdate: Whether the parent component updates its status
    2. The parent componentcomponentWillUpdate: Before the parent component status is updated
    3. The parent componentrender: The parent component is being updated
    4. Child componentscomponentWillReceiveProps: child components will receive newProps
    5. Child componentsshouldComponentUpdate: Whether to update the status of the child component
    6. Child componentscomponentWillUpdate: Before the child component status is updated
    7. Child componentsrender: The child component is being updated and mounted
    8. Child componentscomponentDidMount: The child component is successfully mounted
    9. The parent componentcomponentDidMount: The parent component is successfully mounted
  • When a component is to be uninstalled:
    1. componentWillUnmount: Before components are uninstalled

There are a few caveats:

  • shouldComponentUpdateMeaning whether or not to update his status, so he should have oneBooleanType, and the default istrueWhen you write the hook, do not forget to write the return value. This interval is usually used to make some judgment about updating the value.
  • shouldComponentUpdateThere are two parametersnextProps: the newpropsnextState: the newstateThey have not yet been updated to the component.
  • usesetStateIt goes through the life cycleshouldComponentUpdate, but useforceUpdateNot when, but directly tocomponentWillUpdateThe life cycle

After React 16

Comparison of old and new life cycles:

  1. In the new lifecycle, three lifecycle functions have been (and will be) dropped:
    • componentWillMount
    • componentWillReceiveProps
    • componentWillUpdate
  2. Two new lifecycle functions have been added:
    • getDerivedStateFromProps

    • getSnapshotBeforeUpdate

Here’s the process:

  • Self component mounting:
    1. constructor: constructor (initialization)
    2. getDerivedStateFromPropsFrom:propsGets derived fromstate
    3. render: The component is being mounted
    4. componentDidMount: The component is mounted
  • When the parent component is updated
    1. The parent componentgetDerivedStateFromPropsFrom:propsGets derived fromstate
    2. The parent componentshouldComponentUpdate: Determines whether to update the status
    3. The parent componentrender: The parent component is being mounted
    4. Child componentsgetDerivedStateFromPropsFrom:propsGets derived fromstate
    5. Child componentsshouldComponentUpdate: Determines whether to update the status
    6. Child componentsrender: The child component is being mounted
    7. Child componentsgetSnapshotBeforeUpdate: The child component obtains the snapshot before the status update
    8. Child componentscomponentDidUpdate: The child component is updated
    9. The parent componentgetSnapshotBeforeUpdate: Snapshot of the parent component before the status update
    10. The parent componentcomponentDidUpdate: The parent component is updated
  • Component uninstallation
    1. componentWillUnmount: Before components are uninstalled

There are also a few caveats:

  • getDerivedStateFromPropsYou need to define an instance itself, so it’s a static method
  • getDerivedStateFromPropsThere are two parameters, one is currentpropsandstate
  • The state of the component depends at any time if neededpropsYou can usegetDerivedStateFromProps, but the usage scenarios are rare and can be defined therestate
  • getSnapshotBeforeUpdateThere are two parameters, one before the status updatepropsstate, and has a return value (snapshot), which is generally used as an indication of the status of the update.
  • componentDidUpdateThere are three parameters, one before the status updatepropsstate, and beforegetSnapshotBeforeUpdateThe returned snapshot.
  • What else is the same as the old life cycle

Component list rendering, conditional rendering, and DOMDiffingalgorithm

1. Component list rendering

Sometimes we need to create some DOM elements or components in batches, such as: news list, tweet list, friend list, etc. You will find that lists are often used in the development process, but it is very tedious to write the DOM back one by one. We can use arrays to store data, and we can use arrays to loop through data. Here’s an example:

class Demo extends React.Component{
    state = {
        arr: [a, b, c],
    }
    render(){
        / / output ABC
        return (
            <div>
                <ul> {stus} </ul>
            </div>)}}Copy the code

As you can see, the React output array loops out all the elements directly, so all we have to do is add labels around each element, and that makes for a list rendering. Here we can render the list using JSX syntax with ES6 statements. Go directly to the code:

class Demo extends React.Component{
    state = {
        stus: [{id: "001".name: "Xiao Ming".age: "28"},
            {id: "002".name: "Little red".age: "26"},],}render(){
        return (
            <div>
                <ul>
                    {
                        this.state.stus.map(item =>{
                            return <li key={item.id}>{item.name}---{item.age}</li>})}</ul>
            </div>)}}Copy the code

2. Use of keys

Some people have noticed that when I write a list render, I always put a key attribute on each tag. Why? The key is used to add a unique identifier to the current label, which can be used to calculate the React Diffing algorithm

3. Diffing algorithm

When the state changes, React generates a new virtual DOM based on the new state and diff the new virtual DOM with the following rules:

  1. In the old virtual DOMTo find theThe same key as the new virtual DOM
    • If the contents of the virtual DOM remain the same, the previous real DOM is used
    • If the contents of the virtual DOM change, a new real DOM is generated and replaced
  2. If no key is found in the old virtual DOM that is the same as the new virtual DOM, a new real DOM is created based on the data and then rendered to the page

Using index as the key may cause problems

  • Adding or deleting data in reverse order will result in unnecessary real DOM update and affect efficiency
  • DOM with input classes in the structure will result in incorrect DOM updates and interface rendering problems
  • Using index as the key is fine if you are only displaying data

React scaffolding

Congratulations, you’ve finally made it to the scaffold, where you can generate everything with one click instead of referencing it yourself. What is scaffolding? Scaffolding is the structure of a house, so to speak. Other people have helped you build the structure of your house. You don’t have to do it yourself. React has its own scaffolding. The development team helps you build an environment for developing software using React through webpack, Babel, NPM and other methods. It no longer needs to create folders and import React and other repeated operations, which is more beneficial for us to write SPA applications (single-page rich applications).

1. Install React scaffolding

Type in your own command line window (existing Node environment required) :

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

Install create-React-app scaffold globally

2. Create the React app

Create-create-app Specifies the name of an applicationCopy the code
  • The application name should not contain uppercase letters and special characters
  • Use English names instead of Chinese names

3. File parsing

The most common files in the project file are as follows:

  • Node_modules —— NPM package location
  • The public —— command is used to store static files
  • src—— Where the project code is stored
    • Components —— is used to store the folder of common components
    • Page —— Folder used to store pages
    • App.js— — — — — – the root component
    • App.css—— Style of the root component
    • index.js—— Project entry file
    • index.css—— Common styles for projects
  • .gitgnore— — — — — – writegitConfiguration file of
  • package.json—— Project configuration file
  • README.md—— Project Information

Remember our picture of componentization

The APP is the root component, and other components, such as Header and Aside, are added to the root component by writing other components.

4. NPM instructions

NPM start // Use webpack-dev-server to start the service to view the application NPM build // package to generate the production file NPM test // Software test (not commonly used) NPM eject // Expose all configuration files (uncommon and not recommended)Copy the code

Use of React-Router

1. What is react-router

React-router was created for the React SPA application to operate front-end routing.

(1) Front-end routing (maybe a little straightforward)

The front-end routing is handled through a new HTML5 API, History, which works by making url addresses change without triggering a reload and javascript can listen for changes. There are two types:

  • HashRouter:The url address barthe#At the back of theHash value

  • BrowserRouter: Using the browserHistory APIIs not included in the address bar#, it looks more beautiful

In either case, the redirect function of the URL is not triggered

(2) the SPA applications

SPA full name Single Page Web Application, as the name implies, is a Single Page Application, using javascript for real-time rendering to update the Page. That is, to determine what components should be loaded on the page through the current route to render different pages and effects.

2. Use the react – the router

(1) Installation and use

Open a command line window in the project folder for an NPM download

npm i react-router-dom -S
Copy the code

Note: We downloaded react-router-dom instead of react-router.

  • react-router: provides therouterCore API. Such asRouter,Route,SwitchAnd so on, butThere is no API for DOM manipulation for routing hops;
  • react-router-dom: provides theBrowserRouter,Route,LinkSuch as API,You can control routing by triggering events through DOM operations.

React-router-dom contains react-router, so we select react-router-dom.

(2) Common components

A. Route forwarding

In multi-page applications, the A TAB is usually used for page hopping

<a href="http://localhost:3000">The jump page</a>
Copy the code

A react-router is used in a rich application that uses a single page

import {Link, NavLink} from "react-router";
Copy the code
<Link activeClassName="nav-active" className="nav" to="/about">About</Link>
<NavLink activeClassName="nav-active" className="nav" to="/home">Home</NavLink>
Copy the code
  • activeClassName: If it is in the current route, the corresponding component automatically adds this class
  • className: The name of the current component class
  • to: Indicates the route corresponding to the current component

Both the Link component and the NavLink component can redirect routes. The difference is that the NavLink component of the current route automatically adds class: active, while the Link component does not.

B. Register routes
import {Route} from "react-router";
Copy the code
<Route path="/home" component={Home}></Route>
<Route exact path="/about" component={About}></Route>
Copy the code
  • path: Indicates the route to be monitored
  • component: Indicates the component to be bound to the route
  • exact: This parameter is optionalfalse, whether to select Strict match

If the current route corresponds to the route bound to the routing component, the bound component is displayed.

(a) Routes are strictly matched and fuzzy matched

There is not only one level of routing, sometimes there are multiple levels of nesting, such as this one:



Fuzzy matchingandStrict matchingRefers to the matching mode of the current component to the current route:

  • Fuzzy matching: If the current route is equal to or contains the matched route (note the hierarchy), enable this component
    • http://localhost:3000/home/a/b/cContains routes/home
    • http://localhost:3000/a/b/home/cNo route is included/home(The hierarchy is wrong)
  • Strict matching: This component is enabled only when the current route is equal to the matched route
    • http://localhost:3000/homeThen the route is and/homeequal
    • http://localhost:3000/home/aThen the route is and/homeNot equal to the
C. Redirect routes

What if you have the route /home set up, but some user enters /nothing in the address bar and you haven’t registered the route? At this point, you can redirect the route to Tung Chung Road. For unregistered routes, they will be redirected to one of the routes specified by you. This is called the redirection route. Often used as a route jump for 404, page loss, etc.

import {Redirect, Route} from "react-router";
Copy the code
<Route ./>
<Route ./>
<Redirect to="/home"/>
Copy the code
  • to: Which route to redirect to?

Redirect must be placed under all routes. If none of the routes matches, the Route is redirected to the specified Route.

D. the Switch routing

If you want to render only one of the three routes, you can use the Switch component. If you want to render only one of the three routes, you can use the Switch component. Use the Switch component to wrap all routes and Redirect. When multiple matching routes occur, only the first matching component is rendered.

import {Switch, Route, Redirect} from "react-router";
Copy the code
<Switch>
    <Route ./>
    <Route ./>
    <Redirect to="..."/>
</Switch>
Copy the code
E. the router

If you want to use the routing jump component and the routing component, you need a router component, and the router component must wrap both components.

import {HashRouter, BrowserRouter} from "react-router";
Copy the code

Generally, we wrap the router around the root component so that the entire React application can use the routing component.

ReactDOM.render( 
    <BrowserRouter>
        <App/>
    </BrowserRouter>.document.querySelector("#root"));Copy the code

There are two types of router components, a HashRouter and a BrowserRouter, which correspond to the two routing modes.

(3) Routing components

Routing components versus generic components

  1. Write different
    • General components:<Demo></Demo>
    • Routing components:<Route path="/demo" component={Demo}/>
  2. Different storage locations
    • General components: Components folder
    • Routing component: Page folder
  3. Accept topropsdifferent
    • Generic component: What does it receive when passed according to the component label
    • Routing labels: Receive three fixed attributes
{
  "history": {
    "length"18."action""PUSH"."location": {
      "pathname""/home"."search"""."hash"""."key""tvfyve"}},"location": {
    "pathname""/home"."search"""."hash"""."key""tvfyve"
  },
  "match": {
    "path""/home"."url""/home"."isExact"true."params": {}}}Copy the code

3. Set routine by

Let’s say we have a routing component called Home, and we use a Link in the root component to jump to that route. The current route is/Home. There are two links in the Home component, one to /home/message and the other to /home/news, and then there are other routing components in the component. This is where the nested approach comes in. The code looks like this:

class Home extends Component{
    render(){
        return (
            <div>
                <Link to="/home/message">Message</Link>
                <Link to="/home/news">News</Link>
                <hr/>
                <Route path="/home/message" component={Message} />
                <Route path ="/home/news" component={News} />
            </div>)}}Copy the code

4. Programmatic routing

If we want a user to click the button to log in, if he is a teacher, he will go to the teacher page, and if he is a student, he will go to the student page. Obviously, this cannot be completed by Link alone. We can redirect the route through JS (also react-router is written based on the History API).

class Message extends Component {
    state = {
        messageArr:[
            {id:"01".title"1"},
            {id:".".title"2"},
            {id:"3".title"3"]}},// Programmatic routing navigation
    pushShow = (id, title) = >{
        // Push jump + takes params parameter
        this.props.history.push(`/home/message/detail/${id}/${title}`);
        
        // Push jump + takes the search parameter
        // this.props.history.push(`/home/message/detail? id=${id}&title=${title}`);
        
        // Push jump + carries the state parameter
        // this.props.history.push(`/home/message/detail`, {id,title});
    }
    replaceShow = (id, title) = >{
        // Replace jump + takes params
        this.props.history.replace(`/home/message/detail/${id}/${title}`);
        
        // Replace jump + takes the search parameter
        // this.props.history.replace(`/home/message/detail? id=${id}&title=${title}`);
        
        // Replace jump + takes state
        // this.props.history.replace(`/home/message/detail`, {id, title});
    }
    / / back
    goBack = () = >{
        this.props.history.goBack();
    }
    / / to go forward
    goForward = () = >{
        this.props.history.goForward();
    }
    // Jump to the specified location
    go = () = >{
        // Take two steps forward
        this.props.history.go(2);
        
        // Take two steps back
        this.props.history.go(-2);
    }
    render() {
        const {messageArr} = this.state;
        return (
            <div>
                <ul>
                    {
                        messageArr.map(item=>{
                            return (
                            <li key={item.id}>
                                <Link to={` /home/message/detail/ ${item.id} / ${item.title} `} >{item.title}</Link>
                                &nbsp;<button onClick={()= >Enclosing pushShow (item id, the item title)} > push view</button>
                                &nbsp;<button onClick={()= >Enclosing replaceShow (item id, the item title)} > replace view</button>
                            </li>)})}</ul>
                <hr/>
                <Route path="/home/message/detail/:id/:title" component={Detail} />
                <button onClick={this.goBack}>goBack</button>
                &nbsp;
                <button onClick={this.goForward}>goForward</button>
                &nbsp;
                <button onClick={this.go}>go</button>
            </div>)}}Copy the code

To summarize the above code:

  1. Programmatic routing is all throughpropsIn thehistoryObject (all methods on the object, called as:this.props.history.xxx)
  2. Common methods:
    • Push (route[, state]): Jump to the specified route (with history)

    • Replace (route[, state]): jump to the specified route (no history)

    • GoBack (): goBack one

    • GoForward (): one forward

    • Go (num): Indicates the number of steps to be taken. If num is positive, it is forward; if num is negative, it is backward.

5. WithRouter components

Sometimes we want to use the functions of the routing component in other components. For example, the navigation bar should be a public component, but the navigation link function is the function of the routing component. What should we do? In react-Router, there is a way to make regular components function as routing components: the withRouter() method. Check out the demo:

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

class Header extends Component {
    // After withRouter, this component can also be used as a routing component
    goBack = () = >{
        this.props.history.goBack();
    }
    go = () = >{
        this.props.history.go(2);
    }
    goForward = () = >{
        this.props.history.goForward();
    }
    render() {
        return (
            <div>
                <h1>This is a React-router-dom Test!</h1>
                <button onClick={this.goBack}>goBack</button>
                &nbsp;
                <button onClick={this.goForward}>goForward</button>
                &nbsp;
                <button onClick={this.go}>go</button>
            </div>)}}// withRouter is used to add component-specific functionality to a generic component, returning a new component
export default withRouter(Header);
Copy the code

Parameter passing between routing components

For content passing between a parent and child component, you can use props to pass parameters, but the routing component doesn’t have its own tag. How do you pass parameters? If you remember the routing component-specific props, we can take advantage of some features of the History API to pass parameters between routing components in three ways.

  • params
  • search
  • state

1. Pass the params parameter

/ / the parent component
class Parent extends Component {
    state = {
        messageArr:[
            {id:"01".title"1"},
            {id:".".title"2"},
            {id:"3".title"3"]}},render() {
        const {messageArr} = this.state;
        return (
            <div>
                <ul>{messagearr.map (item=>{// pass params parameter return to the routing component<li key={item.id}><Link to={` /home/message/detail/ ${item.id} / ${item.title} `} >{item.title}</Link></li>})}</ul>
                <hr/>{/* declare to accept the params parameter, which can be obtained in the params attribute of the match attribute in props */}<Route path="/home/message/detail/:id/:title" component={Child} />
            </div>)}}Copy the code
/ / child component
class Child extends Component {
    state = {
        contentArr:[
            {id:"01".content"Hello China"},
            {id:".".content"Hello world"},
            {id:"3".content"Hello, handsome."]}},render() {
        console.log(this.props);
        // Get the params parameter
        const {id, title} = this.props.match.params
        const findResult = this.state.contentArr.find(obj= >obj.id == id).content;
        return (
            <div>
                <ul>
                    <li>ID: {id}</li>
                    <li>TITLE: {title}</li>
                    <li>CONTENT: {findResult}</li>
                </ul>
            </div>)}}Copy the code

When passing parameters with params, you can clearly see that the parameters are presented as routes, for example:

  • 1 / article 32 http://localhost:3000/home/message/ users

User 1 and article 32 above the class, this is the parameter passed. Parameters passed in the params mode can be used only after they are declared to be accepted in the route.

<Route path="/home/message/detail/:id/:title" component={Child} />
Copy the code

The following :id and :title are mutable routes that can be received with props match.

const {id, title} = this.props.match.params
Copy the code

2. Pass the search parameter

So this is the get-dependent request.

  • http://localhost/home/message?id=1&title=abc

So javascript can get to the URL, right? The following request body. So we can modify the label returned from the map above

<li key={item.id}><Link to={` /home/message/detail?id=${item.id}&title=${item.title}`} >{item.title}</Link></li>
Copy the code

In this mode, you do not need to declare receive in the route. Receive using the location in props

const search = this.props.location.search;
// Obtain the format:? Id =xxx&title= XXX
const {id, title} = qs.parse(search.slice(1));
Copy the code

3. Pass the state parameter

Data transfer via HistoryAPI:

<li key={item.id}><Link to={{pathname:` /home/message/detail`, state:{id:item.id.title:item.title}}} >{item.title}</Link></li>
Copy the code

Nothing needs to be added to the route link, nor does the route need to declare receipt. More beautiful. Get the state property in the location of props

const {id, title} = this.props.location.state;
Copy the code

4. Comparison of the three

Routing components pass arguments less often because they all have dependencies on something:

  • params: Depends on routing links, links are not beautiful
  • search: Depends on routing links, links are not beautiful
  • state: Depends on the history (HistoryAPI), the link is beautiful, but an error (no history) will be reported when you enter the link directly.

So try to use other methods of passing arguments, and if you do use them at all, limit them to:

  1. params(Most commonly used)
  2. search(More commonly used)
  3. state(Used sparingly)

Use of redux

Let’s assume that our components look like this diagram, with components nested within each other. Component A and component F use the data in component E. What should we do?

  • Method 1: Through continuouspropsPass parameters, but this is very time-consuming and laborious
  • Method 2: UsePubsub.jsTo publish/subscribe messages
  • Method 3: Usereact-reduxCentralized data management

Redux can be seen as a steward, helping to store public data.

1. Install the story

npm i redux -S
Copy the code

2. Core concepts

Redux has three core concepts

  1. action:
    • The object of the action (action content)
    • Contains two attributes: a.type: indicates the attribute. The value isstringB. the only necessary attributedata: data attribute. The value isAny type, optional properties (how to do it)
    • Such as:{ type: "ADD_STUDENT", data: { name: "tom", age: 18 } }
  2. reducer:
    • Used to initialize state and process state (to initialize and manipulate data)
    • When processing, according to the oldstateandactionAnd produce newstateThe pure functions
    • There are two arguments, one for the previous state (prevstate) and the action object (action)
  3. store:
    • willstate,action,reducerConnected objects (brain)

We can think of Redux as a restaurant, and we are the customer (component). We ask the server (Action) to order the food and other operations. After the server conveys to the manager (store), the manager orders the reducer to cook the food

3. Basic use

(1) Create a folder

Create a redux folder in the SRC folder to store redux-related content

  • Compnoent —— Stores folders related to components
  • redux— — — — — –reduxRelated content folder
    • actions— — — — — –actionRelated content folder
    • reducers— — — — — –reducerRelated content folder
    • constant.js—— stores conventionally named files
    • store.js— — — — — – writestoreThe file

I’ll walk you through them one by one. So let’s write the simplest redux

/** * store.js * This file is dedicated to exposing one store object. There is only one store object in the entire application */
// Introduce the createStore, which is designed to create the core store in Redux
import {createStore} from "redux";
// Import the Reducer as the Count component service
import countReducer from "./count_reducer";
const store = createStore(countReducer)
// Expose the store object
export default store;
Copy the code
/** * / reducer / count.js * 1. This file is used to create a reducer for the Count component. The reducer is essentially a function * * 2. The reducer function receives two parameters: the preState, the action object * * 3. Reducer */ is automatically called once (initialized)
// The state of initialization
const initState = 0;
export default function countReducer(preState = initState, action){
    if(preState === undefined) preState = 0; 
    // Get type, data from the Action object
    const {type, data} = action;
    // How to process the data according to the type
    switch (type) {
        case 'increment'// data
            return preState + data;
        case 'decrement'// If we subtract
            return preState - data;
        default:
            returnpreState; }}Copy the code
// / Component / Count.js 
import React, { Component } from 'react'
/ / into the store
import store from ".. /.. /redux/store";
export default class Count extends Component {
    / / add
    increment = () = >{
        const {value} = this.selectNumber;
        // Send the action object to the store
        store.dispatch({
            type"increment".data: value*1})}render() {
        return (
            <div>
                <h1>The current sum is: {store.getState()}</h1>
                <select ref={c= >this.selectNumber = c}>
                    <option value="1">1</option>
                    <option value="2">2</option>
                    <option value="3">3</option>
                </select>
                <button onClick={this.increment}>+</button>
            </div>)}}Copy the code

That’s the minimalist redux, let’s analyze the process:

  1. writeCountComponent, createCountComponent correspondingReducerfile
  2. writeReducerAnd throw: :
    • ReducerIt’s a pure function
    • Usually useSwitchforactionIn thetypeThe judgment of the
    • The function returns the modified value
  3. createstoreAnd write the code:
    • Method of usecreateStore()Method to create onestore, the parameter is onereducer
    • Write it upCountThe component’sreducerThe import
  4. Introduced in a componentstoreAnd make the call:
    • In a method by usingdspatch()Methods tostorepassaction
    • dispatchIs an object (i.eactionAction object)

(2) Usage process

The above enables the creation of a rough process, while the rough process used is like this:

  1. storeIt is automatically called once during initializationreducerThe value is initialized
  2. Component activationactionstore.storeDetermine the value and distribute the value to the correspondingreducer
  3. reducerAccording to theactionIn thetypeThe data is processed and the new value is returned
  4. storeReceive the returned new value and replace the old one
  5. Through the method ofstore.getState()Gets the currentstoreOn the value of the

(3) Use asynchronous redux

If we need to use asynchronous Redux, we need another plugin: Redux-Thunk

npm i redux-thunk -S
Copy the code

This is a piece of middleware designed to help with asynchronous redux. The value of an asynchronous action is a function in which the normal dispatch() operation is performed

export const createIncrementAsyncAction = (data, time=500) = >{
    // Return an action
    return () = >{
        setTimeout(() = >{ store.dispatch(createIncrementAction(data)); }, time); }}Copy the code

We also need to set up the store to support implementing middleware. Redux’s applyMiddleware() method will load the middleware. Its parameter is middleware. ApplyMiddleware () is then introduced as the second parameter to createStore().

// store.js
// Introduce applyMiddleware specifically for implementing middleware
import {createStore, applyMiddleware} from "redux";
// Import the Reducer as the Count component service
import countReducer from "./count_reducer";
// Redux-thunk is introduced to support asynchronous actions
import thunk from "redux-thunk";
// Expose the store object
export default createStore(countReducer, applyMiddleware(thunk));
Copy the code

(4) Listen for status changes

Did you notice that although the status in redux did change, the page did not change? Remember which function was used for page rendering? Render () function. However, this does not help us call the render() function when the redux state changes, so we need to manually render the page in real time. Here we use the subscribe() method on the Redux store to listen for changes in the state of the redux. The parameter is a function that allows us to operate. We usually write it on the root tag (to be simple, not every component that uses redux).

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import store from "./redux/store"
ReactDOM.render(
    <App />.document.getElementById('root'));// Simplified writing
store.subscribe(() = >{
  ReactDOM.render(
      <App />.document.getElementById('root')); })Copy the code

4. Precautions

  1. Generally used toreduxThere must be more than one component to use, so create oneactionsandreducersUsed to store multipleactionreducer
  2. Same as above,storeThere must be more than onereducer, so we usereduxthecombineReducers()Method to integrate all of thereducer
    • combineReducers()The argument to a method is an object that holds all of thereducer
import {createStore, applyMiddleware, combineReducers} from "redux";
import countReducer from "./reducers/count";
import personReducer from "./reducers/person";
import thunk from "redux-thunk";
// Aggregate all reducers
const allReducer = combineReducers({
    count: countReducer,
    persons: personReducer,
});
export default createStore(allReducer, applyMiddleware(thunk));


Copy the code
  1. becausereduxThere are many problems in the design, such as:
    • Individual components need to do: withstoreContact, get data, listen for changes, distributeactionObject and so on. One component is responsible for too many things.
    • Need additional listeningreduxTo update the status and render the page.
    • So someone is rightreduxWas optimized to launch another libraryreact-redux(Rest assured, nothing different, just a little more optimization, more on that later)
  2. Can not useredux“Do not useredux(whetherreduxorreact-redux)
  3. Can not useredux“Do not useredux(whetherreduxorreact-redux)
  4. Can not useredux“Do not useredux(whetherreduxorreact-redux)

Understanding and usereact-redux

As mentioned above, React-Redux is actually the upgraded version of Redux, which has been optimized in many places. However, before learning react-Redux, we need to do some optimization knowledge of Redux.

1. Use container components and UI components

The goal is to split up the components’ activities into the UI component (internal component) and the container component (external component). The two components communicate with each other using props. The container component uses the state to change the status of requests to the store, and uses the state to write pages, update rendering, and so on. Let the UI components do the work.

Once you know this, you can start using React-Redux

2. Install the react – story

npm i react-redux -S
Copy the code

I won’t say much about that.

3. Create a folder

For container components, we use the containers folder for storage.

  • Containers —— is used to store a folder for container components
  • redux—— For storagereact-reduxRelated folders

4. Create container components

The container components are created using the connect() method of React-Redux.

// Introduce the UI component for Count
import Count from ".. /.. /components/Count";
// Introduce connect to connect UI components to redux
import { connect } from 'react-redux'

// The return value of this function is passed to the UI component as state
function mapStateToProps(state){
    return {
        count: state,
    }
}
// The return value of this function is passed to the UI component as a method of operation state
function mapDispatchToProps(dispatch){
    return {
        add: data= >{
            console.log(1234); }}}export default connect(mapStateToProps, mapDispatchToProps)(Count);
Copy the code

Create and expose a container component for a Count component using connect()(). Connect is called with two arguments and must be a function.

  • mapStateToProps( state ): The return value of this function is treated asstatePass to the UI component
    • stateParameters:statereact-reduxThe default is okstore.getState()
  • mapDispatchToProps( dispatch ): The return value of this function is treated asMethods of operating statesPass in an object to the UI component (see the code below).
    • dispatchParameters:dispatchreact-reduxThe default forstore.dispatchmethods

Here is just for convenience, you can use the grammar sugar when using.

A few points to note:

  1. Generally, the UI components are written in a file with the container components, and the company requirements (usually containers) are seen as to which folder exists.
  2. Container componentstoreNot by introduction, but aspropsOf the label passed to the container component.<Count store={store} />
  3. Sugar = sugar
// Introduce the UI component for Count
import Count from ".. /.. /components/Count";
// Introduce connect to connect UI components to redux
import { connect } from 'react-redux'

// Simplified writing
export default connect(
    state= > ({count: state}),
    {
        add: data= > console.log(1234, data)
    }
)(Count);
Copy the code

5. The Provider component

If you have many container components, wouldn’t it be too cumbersome to pass each container component into a Store? So React-Redux provides a Provider component to handle this problem. Just use it at the root and pass the store in. It can automatically determine which components need to use the Store and pass it to it.

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import store from "./redux/store"
// Optimization 3: Use the built-in Provider to automatically determine which components need to be stored and import them automatically
import { Provider } from "react-redux";
ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>.document.getElementById('root'));Copy the code

6. Listen for the status change

Do you notice that my code above has stopped writing store.subscribe() to listen for the state change because the connect component we created for the container already listens for us?

7. Communication between container components

It’s actually quite simple, remember the first argument of connect’s first function? The UI component is passed props and its argument is state, which is store.getState(). However, your store.getState() is no longer a simple value, but all the reducer objects, so we can get the values of other container components in it.

export default connect(
    state= > ({count: state.count, personLength: state.persons.length}),
    {
        increment: createIncrementAction,
        decrement: createDecrementAction,
        asyncIncrement: createIncrementAsyncAction,
    }
)(Count);
Copy the code

8. File specification

So many things have been created, some can be integrated, let’s fix:

  • containers—— folder for container components (UI components are written together with container components)
    • Count.js —— CountContainer components for
    • Person.js —— PersonContainer components for
  • redux—— For storagereact-reduxRelated folders
    • Actions —— Used to store all action folders

      • count.js—— For storageCountThe component’saction
      • person.js—— For storagePersonThe component’saction
    • Reducers —— is used to save all reducer folders

      • count.js—— For storageCountThe component’sreducer
      • person.js—— For storagePersonThe component’sreducer
      • index.js—— is used to store summariesreducerThe file (combineReducers()Methods)
    • Constant.js —— is used to store some common named files

    • Store. js —— React-redux store file

Again, don’t use this if you can!!

React16.8 with some extensions

1. The lazy () and Suspense

Before, all components were loaded together, which would bring a large burden to the server, so React introduced lazy() to load components on demand. Along with Suspense comes Suspense, which addresses the white screen that components use to show other content while they are being loaded.

import React, { Component, lazy, Suspense } from 'react'
import {Route, Link} from "react-router-dom"

// import Home from "./Home";
// import About from "./About";
import Loading from "./Loading";
The lazy() method takes a function that returns the component to load
const Home = lazy(() = >import("./Home"))
const About = lazy(() = >import("./About"))
export default class index extends Component {
    render() {
        return (
            <div>
                <Link to="/home">Home</Link>
                <Link to="/about">About</Link>
                <hr/>{/* Suspense is used to solve white screens when loading components, showing other content that does not allow lazy loading */}<Suspense fallback={<Loading/>} ><Route path="/home" component={Home}></Route>
                    <Route path="/about" component={About}></Route>
                </Suspense>
            </div>)}}Copy the code
  • lazyThe parameter is a function that usesimportImport a component and return
  • SuspenseThe properties of thefallbackThe property value of theComponent tagNot components
  • SuspenseThe component used is not availablelazyLazy loading.

2. Hook

React16.8 is a spring in the step for functional components because it has hooks to implement state, lifecycle functions, refs, etc. Let’s look at them one by one:

(1) stateHook

We can have functional components implement features that use state:


export default function Demo({
    // useState returns an array with only two elements (only two elements)
    // Element 1 is the state and element 2 is the method to update the state
    // The first call and the underlying storage of the count, so Demo repeated rendering does not reset the count data
    const [count, setCount] = React.useState(0); // The initial value is set to 0
    const [name, setName] = React.useState("Tom");
    function add(){
        // Perform state assignment
        // setCount(count + 1); // Write method 1 to directly override the original state value
        setCount(count= > count+1); // Write 2 as a function, accept the original value of the state, return the new value, and override the original state
    }
    return (
        <div>
            <h3>Name: {name}</h3>
            <h2>Current sum: {count}</h2>
            <button onClick={add}>Click on add a</button>    
        </div>)}Copy the code

(2) EffectHook

You can make functional components implement features like lifecycle hooks:

export default function Demo({
    const [count, setCount] = React.useState(0);
    const [name, setName] = React.useState("Tom");
    function add(){
        setCount(count= > count+1);
    }
    function updName(){
        setName(name= >"Jerry");
    }
    function unmount(){
        ReactDOM.unmountComponentAtNode(document.querySelector("#root"));
    }
    // useEffect takes two arguments, the body of the function and the array of objects to be detected. When the state of the detected object changes, the function is fired
    // When the second parameter is not specified, all elements are detected, which is equivalent to the life cycle function componentDidUpdate
    React.useEffect(() = >{
        // console.log("asdf")
        let timer = setInterval(() = >{
            setCount(count= >count+1);
        },1000);
        return () = >{        // useEffect (componentWillUnmount); // useEffect (componentWillUnmount)
            console.log("unmount")
            clearInterval(timer);
;        }
    },[]) // An empty array is not detected by anyone, and only executes the function once, equivalent to the lifecycle function componentDidMount
    return (
        <div>
            <h2>Current sum: {count}</h2>
            <button onClick={add}>Click on add a</button>
            <h2>Current name: {name}</h2>
            <button onClick={updName}>Change the name to Jerry</button>
            <button onClick={unmount}>Uninstall the component</button>
        </div>)}Copy the code

You can think of useEffect Hook as a combination of three functions:

  • componentDidMount
  • componentDidUpdate
  • componentWillUnmount

(3) refHook

RefHook allows functional components to implement ref-like features

export default function Demo({
    const [count, setCount] = React.useState(0);
    function add(){
        setCount(count= > count+1);
    }
    function show(){
        // Get the text box content
        alert(myInput.current.value);
    }
    // Generate a container
    const myInput = React.useRef();
    return (
        <div>
            <h2>Current sum: {count}</h2>{/* Bind container */}<input type="text" ref={myInput}/>
            <button onClick={add}>Click on add a</button>
            <button onClick={show}>I'm gonna hit show data</button>
        </div>)}Copy the code

This one’s not so hard.

3. Fragment

When you react to render components, when you have more and more components, have you noticed that your DOM is getting more and more hierarchical, which is a little ugly, so there are fragments. Instead of the component’s root tag, you can use the Fragment tag, which is processed during React parsing, to make the generated code more hierarchical.

export default class Demo extends Component {
    render() {
        return (
            The same effect can be achieved with empty tags, but empty tags are not allowed to contain any attributes
            <Fragment key={1}>
                <input type="text"/>
                <input type="text"/>
            </Fragment>)}}Copy the code

4. Context

Context is a new way of communicating between components. It is often used to communicate between ancestor components and descendant components.

// 1. Create a Context
const UserNameContext = React.createContext();
// 1.1 Get Provider and Consumer properties
const {Provider, Consumer} = UserNameContext;
export default class A extends Component {
    state={username"Tom"}
    render() {
        return (
            <div className="a">
                <h1>This is component A</h1>
                <p>My username is: {this.state.username}</p>{/* 2 use the component, the descendant component can receive the value from the value, in this context property (need to declare in advance) */}<Provider value={this.state.username}>
                    <B/>
                </Provider>
            </div>)}}class B extends Component {
    // 3. Accept Context
    static contextType = UserNameContext;   // This method only applies to class components
    render() {
        console.log(this.context);  // Tom
        return (
            <div className="b">
                <h2>This is component B</h2>
                <p>The user name of A is: {this.context}</p>
                <C/>
            </div>)}}function C({
    return (
        <div>
             <div className="c">
                <h3>I am a C component</h3>{/* 3.2 Declare acceptance with Consumer components (both class-based and functional components are acceptable) */}<Consumer>{value=> (" user name of A is: "+ value)}</Consumer>
             </div>
        </div>)}Copy the code

5. PureComponent

Within the component, whenever setState() is executed, the component will render() again even if the state data is not updated. As soon as the component rerender (), it automatically rerender () the child, even if the child does not use any data from the parent. Both of these situations lead to repeated renderings, which can be inefficient.

Efficient: the dish rerender () only if the component’s state or props change.

  • Solution 1: Through the lifecycle functionshouldComponentUpdate()Make data judgment before re-rendering
  • Solution 2: Class components are inheritedPureComponentComponent, automatic data judgment (shallow comparison — address value judgment) (common)
import React, { Component, PureComponent } from 'react'
export default class Parent extends PureComponent {
    state = {carName"Mercedes"}
    changeCar = () = >{
        this.setState(state= >({carName:"Maybach"}));
    }
    // shouldComponentUpdate has two parameters, props and state
    // shouldComponentUp date(nextProps, nextState){
    // console.log(nextProps, nextState); // Props and state for the target to change
    // console.log(this.props, this.state); // Props and state haven't been modified yet
    // return ! this.state.carName === nextState.carName;
    // }
    render() {
        console.log("parent render");
        return (
            <div className="parent">
                <h1>Parent</h1>
                <p>My car is: {this.state.carname}</p>
                <button onClick={this.changeCar}>Click to change</button>
                <Child/>
            </div>)}}class Child extends PureComponent {
    
    // shouldComponentUpdate(nextProps){
    // return ! this.props.carName === nextProps.carName
    // }
    render() {
        console.log("child render");
        return (
            <div className="child">
                <h2>Child</h2>{/ *<p>My father's car is: {this.props. CarName}</p>* /}</div>)}}Copy the code

6. Parent and child components

Let’s go straight to the code:

import React, { Component, PureComponent } from 'react'
import "./index.css"

export default class Parent extends PureComponent {
    state = {carName: "Mercedes"}
    changeCar = () = >{
        this.setState(state= >({carName:"Maybach"}));
    }
    render() {
        console.log("parent render");
        return (
            <div className="parent">
                <h1>Parent</h1>
                <p>My car is: {this.state.carname}</p>{/* The second way to parent component A and component B */} {/*<A>
                    <B/>
                </A>*/} {/* Slot similar to Vue */}<A render={(name)= ><B name={name}/>} / ></div>)}}class A extends PureComponent {
    render() {
        console.log("A render");
        return (
            <div className="a">
                <h2>A</h2>{/* The first way that component A and component B form parent components */} {/*<B/> */}
                {/* {this.props.children} */}
                {this.props.render("Tom")}
            </div>)}}class B extends PureComponent {
    render() {
        console.log("B render");
        return (
            <div className="b">
                <h2>B</h2>
                <p>{this.props.name}</p>
            </div>)}}Copy the code

7. ErrorBoundary

When your component has a parent component relationship, if your child component has an error, it will cause the parent component to collapse, then is there any way to control the error in one component, not let it spread? The answer is yes, there are two functions:

  • getDerivedStateFromError(error)
  • componentDidCatch(error, info)

The code:

import React, { Component, Fragment } from 'react'
import Child from "./Child";
// Error boundaries contain component error messages within a component and prevent them from spreading and crashing the program
export default class Person extends Component {
    state = {
        hasError"".// Used to identify whether the child component has an error
    }
    // This lifecycle function is triggered when an error occurs in the child component, and the parameter is an error message
    // Is only applicable to production environments and can only catch errors generated by the life cycle of descendant components
    static getDerivedStateFromError(error){
        // This is usually used to handle what is returned to the user in case of an error
        console.log("Something went wrong.");
        console.log(error);
    }
    // This lifecycle function is triggered when an error occurs during the component rendering process
    componentDidCatch(error, info){
        // Generally used to count errors, feedback to the fog float, used to inform the programmer to change the bug
        console.log("Render component error");
        console.log(error, info)
    }
    render() {
        return (
            <Fragment>
                <h2>I'm the Parent component</h2>
                {
                    this.state.hasError ? 
                        <h2>The current network is not very good, it is recommended to buy a premium network package</h2> :
                        <Child/>                
                }
            </Fragment>)}}Copy the code

8. Summary of communication modes of components

  • Relationships between components:
    1. Father and son components
    2. Brother components
    3. Great-grandson assembly (cross-stage assembly)
  • Several ways of communication:
    1. props
      1. children props
      2. render props
    2. News subscriptionpubsub. event
    3. Centralized managementredux.dva.react-redux
    4. ConText Producer, consumer pattern
  • Better collocation:
    • Parent and child components:props
    • Sibling component: Message subscription publishing, centrally managed
    • Grandchild components: Message subscription publishing, centralized management,conText

Xiii. Finally

These are my study notes for learning React. In the future, if there are other contents, I will dig into them and write a separate article.

New on the road, also please include. I’m MoonLight, a cub.