React is a JavaScript library for building user interfaces that makes front-end development easier and more efficient. This article will record how to learn React from scratch, and finally use React for small exercises to achieve a simple checklist function.

Because this is an introduction, I practiced by introducing JS into HTML files. To create and start a React project directly (with node and NPM installed first), use the following command:

 npx create-react-app my-app
 cd my-app
 npm start
Copy the code

Official document address: React. Redux and React Router are not covered.

The preparatory work

E6 knowledge

If you are familiar with ES6 you can skip this section.

Need to prepare the knowledge of class, array destruct, object destruct, etc. For ES6 learning, see Introduction to ES6. Just a quick word about classes:

// let container = new Container(100); // The class declaration is not promoted, and using Container here will result in a ReferenceError

// Class declaration
class Container {
  // Constructor is used to create and initialize Container instance objects
  constructor ( totalCapacity ) {
    this.totalCapacity = totalCapacity;

    this.usedCapacity = 0;
    this.contained = [];

    // Methods in class do not automatically bind to instance objects, so we need to bind them manually
    this.add = this.add.bind(this);
    this.remove = this.remove.bind(this);
    this.printContained = this.printContained.bind(this);
  }
  Container.containerinfo (). Static methods are inherited by subclasses
  static containerInfo () {
    console.log('This is a static method \n');
  }
  Add, remove, and printContained are defined on the Container prototype and can be inherited by subclasses
  add (something, volume) { // Add something to the container
    const containedItem = {
      name: something,
      volume
    };
    let used = this.usedCapacity + volume;
    if (used > this.totalCapacity) {
      console.log('This container cannot be put down with a volume of${volume}Items `);
      return;
    }
    this.contained.push(containedItem);
    this.usedCapacity = used;
  }
  remove (something, volume) { // Remove STH from the container
    let containedLen = this.contained.length;
    if (containedLen === 0) return;
    const index = this.contained.findIndex((item) = > item.name === something);
    if (index < 0) return;
    const item = this.contained[index];
    const diff = item.volume - volume;
    switch (true) {
      case diff === 0:
        this.contained.splice(index, 1);
        break;
      case diff > 0:
        this.contained[index] = {
          name: item.name,
          volume: diff
        };
        break;
      case diff < 0:
        console.log('In the container${something}The volume is insufficient${volume}\n`);
        break;
    }
  }
  printContained () {
    this.contained.forEach((item) = > {
      const { name, volume } = item;
      console.log(`${name} ${volume}`); }}})let container = new Container(100); // Classes defined with class must be called with new. Direct execution of Container() generates TypeError

container.add('apple'.20);
container.printContained();
container.remove('apple'.10);
container.printContained();

// If you do not manually assign printContained binding this in constructor, the following two lines of code will be executed with an error
This is undefined in printContained execution, not container (an instance of container).
// const { printContained } = container;
// printContained();

// How static methods are called
// Container.containerInfo();

// Class inheritance
class Box extends Container { // Box inherits the methods on the Container prototype chain
  constructor (totalCapacity, material) {
    // The super method calls the constructor of the superclass, adding the properties of the superclass to the subclass. Call (equivalent to the Container. The constructor. This parameter 1, 2...) parameters ;
    super(totalCapacity);
    this.material = material; // Properties of the Box class
    this.printContained = this.printContained.bind(this);
  }
  printContained () {
    console.log(` box isThe ${this.material}Made of `);
    console.log('Boxes contain:');
    super.printContained(); // We can use the super object to use the superclass method. During the execution of the function, this points to the Box instance}}let box = new Box(100.'wood');
box.add('mango..20);
box.add('watermelon'.10);
box.add('lychee'.30);
box.printContained();
box.remove('mango..10);
box.printContained();

Copy the code

JSX

JSX is a syntax used in React. The following code simply explains JSX:

let test = () = > 1;
let divStyle = { // Note that this is not a direct style, but a style object, style properties are named in the hump
  backgroundColor: '#cfefe7'.fontSize: '15px'.textDecoration: 'underline'
};
let element = (
  <div>{/* () can only have one element */}<h1>JSX</h1>
    <div style={divStyle} >{/* This is how inline styles are added */}<p>This is an "element" created using JSX syntax that is neither HTML nor string.</p>
      <p>You can include any JS expression with {}. For example: {test() + 1}. And JSX itself is also an expression.</p>
      { test() > 0 && <p>This section is displayed when the value of test() is greater than 0</p> }
      <p>Not only can you use native elements such as divs, but you can also include custom components in React.</p>
      <p className="nothing">The attributes of elements in JSX syntax are named with humps.</p>
    </div>
  </div>
);
Copy the code

For more information about JSX, see the official documentation: JSX.

In fact, using ES6 and JSX is not required in React. The official usage is: No ES6, no JSX. This article will use ES6 and JSX in React because the code using ES6 and JSX is more concise and intuitive.

React Developer Tools

useDeveloper toolsIt is easy to view components and their props and states. React Developer tools for Google ChromeReact Developer Tools.

Simple environment

When I open the HTML file in the browser, I get a cross-domain error:

Access to script at ‘file:///Users/… /practice/00.js’ from origin ‘null’ has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https.

So I started a simple Node service and opened the HTML on the local server.

First create the folder practice, and create server.js, practice.html, practice.js, practice.css files in the folder. Server.js creates a simple local server using node.js. The file contents are as follows:

const http = require('http');
const fs = require('fs');
const url = require('url');

const server = http.createServer(function (req, res) {
  let pathname = url.parse(req.url).pathname;
  fs.readFile(pathname.substr(1), function(err, data){
    if (err) {
      res.writeHead(404, {'Content-Type': 'text/html'});
    } else {
      const index = pathname.lastIndexOf('. ');
      const suffix = pathname.slice(index + 1);
      res.writeHead(200, {'Content-Type': `text/${suffix}`});
      res.write(data.toString());
    }
    res.end();
  });
});

server.listen(8080.function () {
  console.log('server is running at http://127.0.0.1:8080');
});
Copy the code

The contents of the practice.html file are as follows:

<! DOCTYPEhtml>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <link rel="stylesheet" type="text/css" href="practice.css" />
</head>
<body>
  <div id="root"></div>

  <! React and react-dom and the compressed version of Babel
  <script src="https://unpkg.com/react@16/umd/react.production.min.js" crossorigin></script>
  <script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js" crossorigin></script>
  <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

  <script type="text/babel" src="practice.js"></script>
</body>
</html>

Copy the code

The contents of practice.js are as follows:

// The reactdom. render method renders the React element into a DOM element
ReactDOM.render(
  <h1>Study the React</h1>.document.getElementById('root'));Copy the code

The content in the pracitice. CSS is as follows:

#root h1 {
  color: green;
}
Copy the code

Run the node server command in the practice directory to start the service. And then access the address http://127.0.0.1:8080/practice.html can see the page green “React to learn the words.

Start learning React

The element

The element is the smallest brick that makes up the React app.

React elements have the same names as familiar HTML elements, such as div, p, etc., but React elements are normal JavaScript objects, while HTML elements are real DOM nodes. React form elements are also used differently. React element attribute names and event bindings are named using a hump. React elements can also use any expression in {}. React form elements are also used differently than HTML form elements.

The React elements:

<div className="card" onClick={test} style={ {color: 'green', fontSize: '12px'} }>Click on the</div>
<input type="text" value={this.state.inputValue} onChange={this.handleChange} />
Copy the code

In the above code, the value of this.state.inputValue is the value of the input box. When the inputValue value in state is set, the value of the input box changes. State is where data is stored in a component, as described in the component section below.

To render a React element into the root DOM node, simply pass them in together with reactdom.render ().

Take the code above:

// The reactdom. render method renders the React element into a DOM element
ReactDOM.render(
  <h1>Study the React</h1>.// This is the React element, which is a normal object
  document.getElementById('root') // This is a DOM image
);
Copy the code

The HTML element:

<div class="card" onclick="test()" style="color: green; font-size: 12px;">Click on the</div>
<input type="text" name="userName" value="RenMo" onchange="handleChange(this.value)" />
Copy the code

component

Components allow you to break up the UI into individual reusable code fragments and think about each fragment independently.

  • Components can be created by functions or by classes.
  • The name of the component must be uppercase.
  • throughpropsGets the properties of the component.
  • throughstatePlace component data throughsetStateSet component data.

Create components through functions

Replace the contents of the practice.js file created above with the following:

function ShowText(props) {
  const { style, content } = props;
  return <p style={style}>{content}</p>;
}
const element = <ShowText content="The React to learn" style={ {color: 'green', fontSize: '30px'}} / >;
ReactDOM.render(
  element,
  document.getElementById('root'));Copy the code

Open the http://127.0.0.1:8080/practice.html, you can see the green “React to learn a few words.

ShowText is a component that is created functionally, and rendering it to the page also requires the reactdom.render function. The function parameter props contains the properties of the defined component. The props of a component are read-only.

Function defined component, if the content needs to be changed, then you must call ReactDOM. Render again. For example, to change the content, you must define a new element and call ReactDOM.

const element = <ShowText content=The React Learning Test Test. style={ {color: 'green', fontSize: '30px'}} / >;
ReactDOM.render(
  element,
  document.getElementById('root'));Copy the code

From the official documentation, we know that to use the React state features without using class, we need to use Hook. Hook will be mentioned below.

Create components through classes

Replace the contents of the practice.js file created above with the following (a simple to-do list example) :

class TodoItem extends React.Component {
  constructor (props) {
    super(props);
    this.state = {
      complete: false
    };
    // Methods defined in the component must be manually bound to this
    this.changeTodoState = this.changeTodoState.bind(this);
  }
  componentDidMount() { // The lifecycle method ------ is triggered the first time the component is rendered into the DOM
    this.timer = null; // To show the effect of task selection, set a timer
  }
  componentDidUpdate () { // The lifecycle method ------ is triggered when the component is updated
    console.log('Component updated');
  }
  componentWillUnmount() { // The lifecycle method ------ is triggered when the component is removed from the DOM
    clearTimeout(this.timer);
  }
  // If you want to pass an argument and an event in the input box click event, put the event at the end of the argument
  changeTodoState (content, event) {
    let value = event.target.value;
    this.timer = setTimeout(() = > {
      if (value) {
        // Change the value of the state by setState
        this.setState({
          complete: true
        });
        // setCompleteItems is a method passed from the parent component. Calling this method will pass the contents of the child components into the parent component
        // When an item in the to-do list is completed, pass the content of the list to the parent component
        this.props.setCompleteItems(content); }},200);
  }
  render () {
    let complete = this.state.complete;
    let content = this.props.content;
    // When complete returns false, not the contents of the component, so an item in the list is hidden
    return (
      (!complete) && 
      <li className="todo-item" key={content.toString()}>{/* if you don't need a bind argument, just write this.changeTodostate in {}. If you want to pass a bind argument, you need to use the bind method */}.<input type="checkbox" onChange={this.changeTodoState.bind(this, content)} / >
        <span>{content}</span>
      </li>); }}class TodoList extends React.Component {
  constructor (props) {
    super(props);
    this.state = {
      completeItems: []};this.setCompleteItems = this.setCompleteItems.bind(this);
  }
  // This method is used to pass the content from the child component to the parent component. Item is the content passed from the child component
  setCompleteItems (item) {
    let completeItems = this.state.completeItems;
    completeItems.push(item);
    this.setState({
      completeItems
    });
  }
  render () {
    let list = this.props.list;
    let todoList = list.map((item) = > <TodoItem content={item} setCompleteItems={this.setCompleteItems}/>);
    return (
      <div>
        <ul className="todo-list">
          {todoList}
        </ul>
        <p>Has been completed: {this.state.com pleteItems. Join (', ')}</p>
      </div>)}}let list = ['Laundry'.'Buy fruit'.'chase play'];
const todoList = <TodoList  list={list} />;
ReactDOM.render(
  todoList,
  document.getElementById('root'));Copy the code

Props is an immutable component property. State is data in a component that can be changed with setState.

The events defined need to be manually bound to this in Constructor, otherwise they cannot be used in the component.

The ShowText class, which inherits from React.component.showtext, contains a render method that is called every time a component updates the render method. The return can be viewed as the official address of the Render method. In the example above, the return is a React element.

React DidMount (componentDidMount) componentWillUnmount (componentDidUpdate) componentDidMount (componentWillUnmount) componentDidUpdate (componentDidUpdate) componentDidMount (componentDidMount) componentWillUnmount (componentDidUpdate) componentDidUpdate (componentDidUpdate) There are other lifecycle hook functions: see React Lifecycle for details.

If you want to change the contents of the parent component from the child component, you can define a method in the parent component as in the example above. The method in the example above is setCompleteItems, and you pass it as the value of some property to the child component. The child component gets the method from the parent component via this.props. Then make corresponding modifications as needed.

Hook

From the above, we can learn that if we want to use state and setState, etc., we must define the component in the way of class, which will lead to redundant and complicated state logic of the component. Hook is used to provide a more direct and simple method for development. Hooks can use React without using class. React has supported hooks since version 16.8.0.

To implement the to-do list example above using hook method, replace the content of practice.js with the following:

Import {useState} from 'react'; The introduction of useState
// Since the browser will convert import to require, it will report require is not defined, so use the following sentence to introduce useState
let useState = React.useState; 
let useEffect = React.useEffect; 

function TodoItem (props) {
  const { content, setCompleteItems } = props;
  // Declare a state variable called complete, which can be changed by setComplete. Complete starts with false.
  const [ complete, setComplete ] = useState(false);
  let timer = null; / / timer
  // useEffect takes a function that executes both when the component is mounted and when it is updated
  useEffect(() = > {
    // Return a function in useEffect that will be executed when the component is cleared
    return () = > {
      clearTimeout(timer)
    }
  });
  function changeTodoState (content, event) {
    let value = event.target.value;
    timer = setTimeout(() = > {
      if (value) {
        // Change the value of complete with setComplete
        setComplete(true);
        setCompleteItems(content); / / here is this originally. Props. SetCompleteItems (content);}},200);
  }
  return (
    (!complete) && 
    <li className="todo-item" key={content.toString()}>{/* if you don't need a bind argument, just write this.changeTodostate in {}. If you want to pass a bind argument, you need to use the bind method */}.<input type="checkbox" onChange={changeTodoState.bind(this, content)} / >
      <span>{content}</span>
    </li>
  );
}

function TodoList (props) {
  const { list } = props;
  const [ completeItems, setCompleteItemsState ] = useState([]);
  useEffect(() = > {
    // Update the document title
    document.title = completeItems.join();
    return () = > {
      document.title = 'listing'; }});const setCompleteItems = (completedItem) = > {
    setCompleteItemsState([...completeItems, completedItem]);
  };
  const unmountComponent = () = > {
    ReactDOM.unmountComponentAtNode(document.getElementById('root'));
  };
  let todoList = list.map((item) = > <TodoItem content={item} setCompleteItems={setCompleteItems}/>);
  return (
    <div>
      <ul className="todo-list">
        {todoList}
      </ul>
      <p>Completed: {completeItems.join()}</p>
      <p onClick={unmountComponent}>Click to manually uninstall components</p>
   </div>)}let list = ['Laundry'.'Buy fruit'.'chase play'];
const todoList = <TodoList  list={list} />;
ReactDOM.render(
  todoList,
  document.getElementById('root'));Copy the code

As you can see, after using hook, you don’t need to use this.state.varName as you do in the class.

(! complete) &&<li class="todo-item" key={content.toString()}>.Copy the code

State hook is used to process data. For effect hook, direct reference is made to the official document:

UseEffect is an Effect Hook that adds the ability to manipulate side effects to a function component. It has the same purpose as componentDidMount, componentDidUpdate, and componentWillUnmount, but is combined into a single API.

When using useEffect, if there is some processing required when the component is unloaded, then useEffect returns a function, and when the effect is cleared, the contents of the returned function are executed. For example, the following code changes document.title every time an item is completed, and when the component is uninstalled, it changes document.title to “list”.

useEffect(() = > {
  // Update the document title
  document.title = completeItems.join();
  return () = > {
    document.title = 'listing'; }});const setCompleteItems = (completedItem) = > {
  setCompleteItemsState([...completeItems, completedItem]);
};
Copy the code

UseState, useEffect, and useContext are some of the basic hooks, but you can also customize them.

The last

The end result of the code exercise is this: the source address, which you can use DownGit to get to a folder of code in your Git repository.