React

I have read the react. js little book by Mr. Beard these days, and I feel I have benefited a lot. I sincerely recommend you to have a look!


Sample code is available here


JSX principle

JSX is essentially a syntactic sugar for React. CreateElement.

JSX is not required to use React. React without JSX is handy when you don’t want to set up the compiler in your build environment.

Each JSX element calls react. createElement(Component, props,… So anything you do with JSX can be done with pure JavaScript.

<div class="root">
  <div class="child">hello man</div>
</div>
Copy the code

Looking at the code above, we can see that each DOM actually contains only three pieces of information: tag names, attributes, and child elements. So, for each DOM element, we can label it with a JS object. The above code can be represented as:

{
  tag: 'div',
  attr: {
    class: 'root'
  },
  child: {
    tag: 'div',
    attr: {
      class: 'child'
    },
    child: 'hello man'}}Copy the code

In React, we use React. CreateElement to convert this js object into a real DOM element. The internal implementation of React. CreateElement is not discussed here.

If we called React. CreateElement in our code and generated the DOM from the js object, the code would look a bit verbose and not quite as simple as we’d like. React invented the JSX syntax. We can write the HTML structure directly in js code, hand it to Babel to compile objects describing the DOM as described above, and then build the real DOM with react.createElement.

Container components

In some business scenarios, we might have to deal with a large number of DOM with the same overall layout but completely different layout content with child nodes, as shown in the following figure:

We can see that although the interior elements of the left and right elements are completely different, they have the same overall layout! At this point, we can use the same name and introduce the same CSS to reduce our workload, but when these elements are located in different components, we need to introduce the same CSS for each component and give them the same class name, which is obviously a bit cumbersome. If we use a common container component, we can simply import the container component and fill it with the appropriate content, which obviously makes the code cleaner and easier to use.

Create a react project with create-react-app (see here for a sample code), clear out some of the irrelevant stuff, and create two new components:

Container.js

import React from 'react';

export default class Container extends React.Component {
  constructor(){
    super()
  }
  render() {return (
      <div>
        Container
      </div>
    )
  }
}
Copy the code

head.js

import React from 'react';

export default class Head extends React.Component {
  constructor() {
    super()
  }
  render() {
    return (
      <div>
        head
      </div>
    )
  }
}
Copy the code

We import these two components in index.js and insert the Head component into the Container component:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import Container from './container';
import Head from './head';


ReactDOM.render(
  <Container>
    <div>hello man</div>
    <Head></Head>
  </Container>,
  document.getElementById('root'));Copy the code

When we open the browser, we see that on the page, instead of head and Hello Man, we see container:

We print the container on the console:

In the props. Children property of the Container, we need to render the content that we inserted into the container.

import React from 'react';

export default class Container extends React.Component {
  constructor(){
    super()
  }
  render() {return (
      <div className="container">
        <div className="head">{this.props.children[0]}</div>
        <div className="body">{this.props.children[1]}</div>
      </div>
    )
  }
}
Copy the code

When we open the browser, we see that the content we filled in the Container component is displayed as expected, and the overall layout structure is as expected. We can fill in specific internal elements according to the specific business.

Note that when we comment out the Head of the Container component, we find that the inserted Hello man does not display properly either:

ReactDOM.render(
  <Container>
    <h1>hello man</h1>
    {/* <Head></Head> */}
  </Container>,
  document.getElementById('root'));Copy the code

props.children
props.children

Higher order component (Document location)

First, let’s look at these definitions:

A higher-order component is a function that takes a component and returns a new one. A higher-order component is a pure function that does not change the original component and has no side effects.

In simple terms, functions that satisfy the following conditions can be called pure functions:

The return result depends entirely on the parameter passed in. There are no side effects in performing weighing. The same input gets the same output. Const gen = math.random () is not pure. (Thanks FateRiddle for pointing it out)

Let’s look at the following two functions to see if they return a result that depends entirely on the argument passed in:

let d = 1;
function add(a,b){
  return a + b
}

function all(c){
  return c + d
}
Copy the code

When we execute add and all, the result of add depends entirely on the value of the parameters a and B passed in. Add (3,6) must return 9, but when all executes, all(3) does not necessarily return 4. When d is 2, All (3) returns 5, so all is not a pure function here, and add is a pure function.

But when we redeclare a variable, rewrite add:

let obj = {
  x: 2
}
function add(obj,b){
  obj.x = 1;
  return obj.x + b
}
Copy the code

We call add(obj,6) again. Although the result of add is still completely dependent on the parameter passed in, the value of the x property of the obj object passed in has changed as a side effect, so add is not a pure function.

A higher-order function is a pure function that does not change the component passed in.

Having said all that, what is the use of higher-order components?

Let’s look at the following two pieces of code:

Component 1: import React from'react';
export default class One extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      higher: 0
    }
  }
  componentWillMount() {let higher = this.props.higher * 2
    this.setState({
      higher: higher
    })
  }
  render() {
    return(<div>{this.state.higher}</div>)}'react';
export default class Two extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      higher: 0
    }
  }
  componentWillMount() {let higher = this.props.higher * 2
    this.setState({
      higher: higher
    })
  }
  render() {
    return (
      <h1>{this.state.higher}</h1>
    )
  }
}
Copy the code

We see that the code is identical except for the label element returned by the component. Both components perform logic processing on the incoming data when componentWillMount, so we can use higher-order components to pull out the common logic code:

const higher = function(Component,data){
  class Higher extends React.Component {
    constructor(props) {
      super(props)
      this.state = {
        higher: 0
      }
    }
    componentWillMount() {
      let higher = data * 2
      this.setState({
        higher: higher
      })
    }
    render() {
      return (
        <Component higher={this.state.higher}></Component>
      )
    }
  }

  return Higher
}
Copy the code

We insert raw components and higher-order components into the page:

let CopyOne = higher(One,30);
let CopyTwo = higher(Two, 40);

ReactDOM.render(
  <div>
    <CopyOne></CopyOne>
    <CopyTwo></CopyTwo>
    <One higher={10}></One>
    <Two higher={20}></Two>
    {/* <Container>
      <h1>hello man</h1>
      <Head></Head>
    </Container> */}
  </div>,
  document.getElementById('root'));Copy the code

Open the browser and we see:


Final words:

This note is a brief review of my understanding of React. If there is anything wrong in the description, please criticize and correct me!