React basic learning notes

React basic learning notes (I)

  • Reference: Teacher Wang Hongyuan's React

React features – declarative programming

  • Declarative programming:
    • Declarative programming is the mode of the whole front-end development: Vue, React, fluent and SwiftUI;
    • It allows us to only maintain our own state. When the state changes, React can render our UI interface according to the latest state;

React development dependency

  • The development of React must rely on three libraries:
    • React: contains the core code necessary for react
    • React DOM: the core code required for react rendering on different platforms
    • babel: a tool for converting jsx into React code
  • The first contact with react will be confused by its cumbersome dependence. For Vue, we just rely on a Vue JS file, but react actually depends on three libraries.
    • In fact, the three libraries perform their own duties, so that each library can only do its own things:
    • Before version 0.14 of react, there was no concept of react DOM, and all functions were included in react.
    • Why split? The reason is react native.
    • The react package contains the core code shared by react and react native.
  • React DOM does different things for web and native:
    • web side: react DOM will say that jsx will eventually be rendered into a real Dom and displayed in the browser
    • Native side: react DOM will say that jsx will eventually render into native controls (such as Button in Android and UIButton in iOS).

Introduce React dependency

  • Add these three dependencies:
    • Method 1: direct CDN introduction
    • Method 2: after downloading, add local dependencies
    • Method 3: manage through npm
  • For the time being, we will directly introduce CDN to practice the following example program:
    • Here is a crossorigin attribute. The purpose of this attribute is to get the error information of the cross domain script
<script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

Hello World

  • Step 1: display a Hello World through React on the interface
  • Note: in the script code of React, we must add type="text/babel" to enable babel to parse the syntax of jsx

  • ReactDOM.render function:
    • Parameter 1: pass the content to be rendered, which can be HTML elements or React components
      • Here we pass in an h2 element, and then we will use the React component
    • Parameter 2: which HTML element will the rendered content be mounted on
      • Here, we have proposed to define a div with id app
    • We can introduce external variables or expressions through {} syntax
<body>
  <div id="app">
  </div>
  <!-- add to React Dependence of -->
  <script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script>
  <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>
  <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

  <!-- Start development -->
  <!-- matters needing attention: use jsx, And hope script Medium jsx The code is parsed, Must be script Add an attribute to the tag  -->
  <!-- jsx characteristic: Outermost layer of multiple labels(root)There can only be one label -->
  <script type="text/babel">
    let message = "Hello World";

    function btnClick() {
      message = "Hello React";
      console.log(message);
      render();
    }

    // <h2>< / H2 >: JSX code
    function render() {
      ReactDOM.render(
        <div>
          <h2>{message}</h2>
          <button onClick={btnClick}>Change text</button>
        </div>,
        document.getElementById("app")
      );
    }

    render();
  </script>
</body>

Hello React – component development

  • You can first encapsulate the previous business logic into a component, and then pass it into reactdom The first parameter in the render function;
  • Here, we temporarily use class to encapsulate components:
    • 1. Define a class (class name is capitalized, component name must be capitalized, and lowercase will be regarded as HTML element), which is inherited from react Component
    • 2. Implement the render function of the current component
      • The jsx content returned in render is the content that React will help us render later

Componentization - data dependency

  • The data in the component can be divided into two categories:
    • Data involved in interface update: when the data variable is, the content rendered by the component needs to be updated
    • Data that does not participate in the interface update: when the data variable is, there is no need to update the content that will be constructed and rendered
  • The data participating in the interface update can also be called participating data flow, which is defined in the state of the current object
    • We can use this in the constructor State = {defined data}
    • When our data changes, we can call this Setstate to update the data, and notify React to perform the update operation
      • During the update operation, the render function will be called again and the interface will be rendered with the latest data.

Componentization – event binding

  • Componentization problem 2: this in event binding
  • Directly define a function in the class and bind this function to the html native onClick event. Who does this function point to?
  • It is undefined by default
    • It's strange that it's undefined;
    • Because in normal DOM operations, this in the listening function is actually a node object (for example, a button object);
    • This time, because React is not directly rendered as a real DOM, the button we write is just a syntax sugar, and its essence is the Element object of React;
    • When listening here, the function bound this by react is undefined by default;
  • In the bound function, we may want to use the current object, such as executing this Setstate function, you must get this of the current object
  • When we pass in a function, we need to bind this function directly
  • Similar to the following writing method: < button onclick = {this. Changetext. Bind (this)} > change text < / button >

Complete example of Hello World component

<body>
  <div id="app">
  </div>
  <!-- add to React Dependence of -->
  <script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script>
  <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>
  <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
  <!-- Start development -->
  <script type="text/babel">
    // Encapsulate App components
    class App extends React.Component {
      constructor() {
        super();
        // this.message = "Hello World";
        this.state = {
          message: "Hello World"
        }
      }
      render() {
        return (
          <div>
            <h2>{this.state.message}</h2>
            <button onClick={this.btnClick.bind(this)}>Change text</button>
          </div>
        )
      }
      btnClick() {
        // this.message = "Hello React";
        // this.state.message = "Hello React";
        // console.log(this.state);
        this.setState({
          message: "Hello React"
        })
      }
    }
    // Rendering Components 
    ReactDOM.render(<App/>, document.getElementById("app"));
  </script>
</body>

Movie list display

<body>
  <div id="app"></div>
  <!-- 1.Introduce dependency -->
  <script src="../react/react.development.js"></script>
  <script src="../react/react-dom.development.js"></script>
  <script src="../react/babel.min.js"></script>

  <!-- 2.to write React code -->
  <script type="text/babel">
    class App extends React.Component {
      constructor() {
        super();

        this.state = {
          message: "Hello World",
          movies: ["Westward Journey", "Inception", "Interstellar crossing", "Wandering the earth"]
        }
      }

      render() {
        const liArray = [];
        for (let movie of this.state.movies) {
          liArray.push(<li>{movie}</li>);
        }

        return (
          <div>
            <h2>Movie List 1</h2>
            <ul>
              {liArray}
            </ul>

            <h2>Movie list 2</h2>
            <ul>
              {
                this.state.movies.map((item) => {
                  return <li>{item}</li>
                })
              }
            </ul>
          </div>
        )
      }
    }

    ReactDOM.render(<App />, document.getElementById("app"));
  </script>

Counter case

 <script type="text/babel">
    class App extends React.Component {
      constructor(pops) {
        super(props);

        this.state = {
          counter: 0
        }
      }

      render() {
        return (
          <div>
            <h2>Current count: {this.state.counter}</h2>
            <button onClick={this.increment.bind(this)}>+1</button>
            <button onClick={this.decrement.bind(this)}>-1</button>
            <img src="" alt=""/>
          </div>
        )
      }

      increment() {
        this.setState({
          counter: this.state.counter + 1
        })
      }

      decrement() {
        this.setState({
          counter: this.state.counter - 1
        })
      }
    }

    ReactDOM.render(<App/>, document.getElementById("app"));
  </script>

Know JSX

  • What is the tag syntax of the assignment to the right of the element variable declaration?
    • It is not a string (because it is not wrapped in quotation marks). It looks like a native HTML, but can we assign HTML to a variable directly in js?
    • In fact, it is not allowed. If we remove type="text/babel", there will be syntax errors;
    • What is it? In fact, it is a jsx syntax;
  • What is JSX?
    • JSX is a JavaScript syntax eXtension, which is also called JavaScript XML in many places, because it looks like an XML syntax;
    • It is used to describe our UI interface, and its completion can be integrated with JavaScript;
    • It is different from the module syntax in Vue. You do not need to learn some instructions in the module syntax (such as v-for, v-if, v-else, v-bind);

Why did React choose JSX

  • React believes that rendering logic is inherently coupled with other UI logic
    • For example, the UI needs to bind events (button, a native, etc.);
    • For example, the data status needs to be displayed in the UI, and when some status changes, the UI needs to be changed;
    • They are inseparable, so React does not separate tags into different files, but combines them together. This place is Component;
  • Writing specification of JSX:
    • The top layer of JSX can only have one root element, so we often wrap a div primitive in the outer layer (or use the Fragment we will learn later);
    • In order to facilitate reading, we usually wrap a parenthesis () in the outer layer of jsx, which is convenient for reading, and jsx can wrap lines;
    • Tags in JSX can be single tags or double tags;
    • Note: if it is a single label, it must end with / >;

Use of JSX

Comments in jsx

JSX embedded variables

jsx embedded expression

JSX embedded expression
  • Operation expression
  • Ternary operator
  • Execute a function
<script type="text/babel">
    class App extends React.Component {
      constructor(props) {
        super(props);

        this.state = {
          firstname: "kobe",
          lastname: "bryant",
          isLogin: false
        }
      }

      render() {
        const { firstname, lastname, isLogin } = this.state;

        return (
          <div>
            {/*1.Operator expression*/}
            <h2>{ firstname + " " + lastname }</h2>
            <h2>{20 * 50}</h2>

            {/*2.Ternary expression*/}
            <h2>{ isLogin ? "welcome back~": "Please log in first~" }</h2>

            {/*3.Make a function call*/}
            <h2>{this.getFullName()}</h2>
          </div>
        )
      }

      getFullName() {
        return this.state.firstname + " " + this.state.lastname;
      }
    }

    ReactDOM.render(<App/>, document.getElementById("app"));
  </script>

jsx binding properties

  • For example, every element has a title attribute
  • For example, img elements have src attributes
  • For example, the a element will have a href attribute
  • For example, an element may need to be bound to a class
  • For example, native uses inline style
<body>
  <div id="app"></div>
  <script type="text/babel">
    function getSizeImage(imgUrl, size) {
      return imgUrl + `?param=${size}x${size}`
    }

    class App extends React.Component {
      constructor(props) {
        super(props);

        this.state = {
          title: "title",
          imgUrl: "http://p2.music.126.net/L8IDEWMk_6vyT0asSkPgXw==/109951163990535633.jpg",
          link: "http://www.baidu.com",
          active: true
        }
      }

      render() {
        const { title, imgUrl, link, active } = this.state;
        return (
          <div>
            {/* 1.Bind common properties */}
            <h2 title={title}>I'm the title</h2>
            <img src={getSizeImage(imgUrl, 140)} alt=""/>
            <a href={link} target="_blank">use Baidu Search</a>

            {/* 2.Bind class */}
            <div className="box title">I am div element</div>
            <div className={"box title " + (active ? "active": "")}>Me too. div element</div>
            <label htmlFor=""></label>

            {/* 3.Binding style */}
            <div style={{color: "red", fontSize: "50px"}}>I am div,binding style attribute</div>
          </div>
        )
      }
    }

    ReactDOM.render(<App />, document.getElementById("app"));
  </script>

React event binding

  • React events are named in camel case instead of pure lowercase;
    • We need to pass in an event handling function through {}, which will be executed when the event occurs
  • Binding problem of this
    • The reason is that we do not call the btnClick function actively, and when the button changes, React calls the btnClick function internally;
    • When it is called internally, it does not know how to bind the correct this;
  • How to solve this problem?
    • Scheme 1: bind displays the bound this to btnClick
    • Scheme 2: use ES6 class fields syntax
    • Scheme 3: pass in the arrow function during event listening (recommended)
<script type="text/babel">
  class App extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
        message: "How do you do",
        counter: 100
      }

      this.btnClick = this.btnClick.bind(this);
    }

    render() {
      return (
        <div>
          {/* 1.Scheme 1: bind bind this (display binding) */}
          <button onClick={this.btnClick}>Button 1</button>
          <button onClick={this.btnClick}>Button 2</button>
          <button onClick={this.btnClick}>Button 3</button>

          {/* 2.Scheme 2: when defining a function, use the arrow function */}
          <button onClick={this.increment}>+1</button>

          {/* 2.Scheme three (recommendation): directly import an arrow function and invoke the function to be executed in the arrow function.*/}
          <button onClick={() => { this.decrement("why") }}>-1</button>
        </div>
      )
    }

    btnClick() {
      console.log(this.state.message);
    }

    // increment() {
    //   console.log(this.state.counter);
    // }
    // this is never bound in the arrow function
    // Add attribute to object in ES6: class fields
    increment = () => {
      console.log(this.state.counter);
    }

    decrement(name) {
      console.log(this.state.counter, name);
    }
  }

  ReactDOM.render(<App/>, document.getElementById("app"));
</script>

Event parameter passing

<script type="text/babel">
  class App extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
        movies: ["Westward Journey", "dominant sea power", "Wandering the earth", "Inception"]
      }
      this.btnClick = this.btnClick.bind(this);
    }
    render() {
      return (
        <div>
          <button onClick={this.btnClick}>Button</button>
          
          <ul>
            {
              this.state.movies.map((item, index, arr) => {
                return (
                  <li className="item" 
                      onClick={ e => { this.liClick(item, index
                      title="li">
                    {item}
                  </li>
                )
              })
            }
          </ul>
        </div>
      )
    }
    btnClick(event) {
      console.log("The button was clicked", event);
    }
    liClick(item, index, event) {
      console.log("li Click happened", item, index, event);
    }
  }
  ReactDOM.render(<App/>, document.getElementById("app"));
</script>

React conditional rendering

<script type="text/babel">
  class App extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
        isLogin: true
      }
    }
    render() {
      const { isLogin } = this.state;
      // 1. Scheme 1: judge by if: there are many logic codes
      let welcome = null;
      let btnText = null;
      if (isLogin) {
        welcome = <h2>welcome back~</h2>
        btnText = "sign out";
      } else {
        welcome = <h2>Please log in first~</h2>
        btnText = "Sign in";
      }
      return (
        <div>
          <div>I am div element</div>
          {welcome}
          {/* 2.Scheme 2: ternary operator */}
          <button onClick={e => this.loginClick()}>
          <hr />
          <h2>{isLogin ? "How do you do, coderwhy": null}<
          {/* 3.Scheme 3: logic and&& */}
          {/* Logic and: One condition does not hold, The latter conditions are
          <h2>{ isLogin && "How do you do, coderwhy" }</h2
          { isLogin && <h2>How do you do, coderwhy</h2> }
        </div>
      )
    }
    loginClick() {
      this.setState({
        isLogin: !this.state.isLogin
      })
    }
  }
  ReactDOM.render(<App />, document.getElementById(
</script>

Conditional rendering -v-show effect

<script type="text/babel">
  class App extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
        isLogin: true
      }
    }
    render() {
      const { isLogin} = this.state;
      const titleDisplayValue = isLogin ? "block": "none";
      return (
        <div>
          <button onClick={e => this.loginClick()}>{isLogin ? "sign out": "Sign in"}</button>
          <h2 style={{display: titleDisplayValue}}>How do you do, coderwhy</h2>
        </div>
      )
    }
    loginClick() {
      this.setState({
        isLogin: !this.state.isLogin
      })
    }
  }
  ReactDOM.render(<App />, document.getElementById("app"));
</script>
  • Example 2:
<script type="text/babel">
  class App extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
        names: ["abc", "cba", "nba", "mba", "dna"],
        numbers: [110, 123, 50, 32, 55, 10, 8, 333]
      }
    }
    render() {
      return (
        <div>
          <h2>Name list</h2>
          <ul>
            {
              this.state.names.map(item => {
                return <li>{item}</li>
              })
            }
          </ul>
          <h2>Digital list(Filter 1)</h2>
          <ul>
            {
              this.state.numbers.filter(item => {
                return item >= 50;
              }).map(item => {
                return <li>{item}</li>
              })
            }
          </ul>
          <h2>Digital list(Filter 2)</h2>
          <ul>
            {
              this.state.numbers.filter(item => item >= 50).map(item => <l
            }
          </ul>
          <h2>Digital list(intercept)</h2>
          <ul>
            {
              this.state.numbers.slice(0, 4).map(item => {
                return <li>{item}</li>
              })
            }
          </ul>
        </div>
      )
    }
  }
  ReactDOM.render(<App />, document.getElementById("app"));
</script>

The essence of JSX

  • In fact, jsx is just react Syntax of the createElement (component, props,... Children) function.
    • All jsx will eventually be converted to react Function call to createElement
createElement needs to pass three parameters:
  • Parameter 1: type
    • Type of current ReactElement;
    • If it is a label element, use a string to represent "div";
    • If it is a component element, the name of the component is used directly;
  • Parameter 2: config
    • All attributes in jsx are stored in config as attributes and values of objects
  • Parameter 3: children
    • The contents stored in the tag are stored in the form of children array;
    • Of course, what if it's multiple elements? React processes them internally

Babel official website

  • We know that the default jsx uses babel to help us with syntax conversion, so the jsx code we wrote before needs to rely on babel.
  • You can quickly view the conversion process on babel's official website: https://babeljs.io/repl/#?presets=react

Write jsx code directly

  • We'll write react ourselves CreateElement Code:
    • We didn't write through jsx, and the interface can still be rendered normally.
    • In addition, in this case, do you still need babel related content? I don't want it any more
      • Therefore, type="text/babel" can be deleted by us;
      • Therefore, < script SRC = ".. / react / Babel. Min.js" > < / script > can be deleted by us

Creation process of virtual DOM

  • We passed react CreateElement finally creates a ReactElement object:
  • What is the function of this ReactElement object? Why did React create it?
    • The reason is that React uses the ReactElement object to form a JavaScript object tree;
    • The object tree of JavaScript is the famous Virtual DOM (Virtual DOM);
  • How to view the tree structure of ReactElement?
    • We can print the previous jsx returned results;
    • Pay attention to the printing of jsx in the following code;
  • The tree structure finally formed by ReactElement is Virtual DOM;

Why use virtual DOM

  • Why adopt virtual DOM instead of directly modifying real DOM?
    • It is difficult to track the change of state: in the original development mode, it is difficult for us to track the change of state, which is inconvenient to debug our application;
    • The performance of operating real DOM is low: the traditional development mode will perform frequent DOM operations, and the performance of this method is very low;
  • DOM operation performance is very low:
    • First, document CreateElement itself creates a very complex object;
    • https://developer.mozilla.org/zh-CN/docs/Web/API/Document/createElement
    • Secondly, DOM operation will cause browser backflow and redrawing, so frequent DOM operation should be avoided in development;

Declarative programming

  • Virtual DOM helped us move from imperative programming to declarative programming
  • React official statement: Virtual DOM is a programming concept.
    • In this concept, the UI is stored in memory in an idealized or virtualized way, and it is a relatively simple JavaScript object
    • We can use reactdom Render synchronizes the virtual DOM with the real dom. This process is called Reconciliation
  • This programming method gives React a declarative API:
    • You just need to tell React what state you want the UI to be;
    • React to ensure that the DOM matches these states;
    • You don't need to directly operate the DOM, but can only be liberated from manually changing the DOM, attribute operation and event handling;

Stage exercise example

  • Main code:
<script type="text/babel">
  class App extends React.Component {
    constructor(props) {
      super(props);

      this.state = {
        books: [
          {
            id: 1,
            name: '<Introduction to Algorithms',
            date: '2006-9',
            price: 85.00,
            count: 2
          },
          {
            id: 2,
            name: '<UNIX Programming art',
            date: '2006-2',
            price: 59.00,
            count: 1
          },
          {
            id: 3,
            name: '<Programming Pearl',
            date: '2008-10',
            price: 39.00,
            count: 1
          },
          {
            id: 4,
            name: '<Code collection',
            date: '2006-3',
            price: 128.00,
            count: 1
          },
        ]
      }
    }

    renderBooks() {
      return  (
        <div>
          <table>
            <thead>
              <tr>
                <th></th>
                <th>Book name</th>
                <th>Publication date</th>
                <th>Price</th>
                <th>Purchase quantity</th>
                <th>operation</th>
              </tr>
            </thead>
            <tbody>
              {
                this.state.books.map((item, index) => {
                  return (
                    <tr>
                      <td>{index+1}</td>
                      <td>{item.name}</td>
                      <td>{item.date}</td>
                      <td>{formatPrice(item.price)}</td>
                      <td>
                        <button disabled={item.count <= 1} onClick={e => this.changeBookCount(index, -1)}>-</button>
                        <span className="count">{item.count}</span>
                        <button onClick={e => this.changeBookCount(index, 1)}>+</button>
                      </td>
                      <td><button onClick={e => this.removeBook(index)}>remove</button></td>
                    </tr>
                  )
                })
              }
            </tbody>
          </table>
          <h2>Total price: {this.getTotalPrice()}</h2>
        </div>
      )
    }

    renderEmptyTip() {
      return <h2>Shopping cart is empty~</h2>
    }

    render() {
      return this.state.books.length ? this.renderBooks(): this.renderEmptyTip();
    }

    changeBookCount(index, count) {
      const newBooks = [...this.state.books];
      newBooks[index].count += count;
      this.setState({
        books: newBooks
      })
    }

    removeBook(index) {
      // Design principle in React: immutability of data in state;
      this.setState({
        books: this.state.books.filter((item, indey) => index != indey)
      })
    }

    getTotalPrice() {
      // 1.for loop mode
      // let totalPrice = 0;
      // for (let item of this.state.books) {
      //   totalPrice += item.price * item.count;
      // }
      // return formatPrice(totalPrice);

      // 2. Filter / map / reduce
      // Parameters of callback function:
      // Parameter 1: the result of the last callback function (the result of the callback function without the last function for the first time, using the initialization value)
      const totalPrice = this.state.books.reduce((preValue, item) => {
        return preValue + item.count * item.price;
      }, 0);

      return formatPrice(totalPrice);
    }
  }

  ReactDOM.render(<App/>, document.getElementById("app"));
</script>

Keywords: Front-end React

Added by headbangerbuggy on Thu, 20 Jan 2022 00:36:04 +0200