34 skills for React development (nearly 1W words)

preface

React is one of the three front-end frameworks and is also a skill in development;
This paper summarizes some skills of React development from the actual development, which is suitable for students who are beginners of React or have some project experience

Source code address

(1) component communication

1.1 props

Subassemblies

import React from "react";
import PropTypes from "prop-types";
import { Button } from "antd";

export default class EightteenChildOne extends React.Component {
  static propTypes = { //propTypes verifies the incoming type. For details, please refer to skill 11
    name: PropTypes.string
  };

  click = () => {
    // Pass child to parent by triggering method
    this.props.eightteenChildOneToFather("This is props Change the value of the parent element");
  };

  render() {
    return (
      <div>
        <div>This is through props Value passed in{this.props.name}</div>
        <Button type="primary" onClick={this.click}>
          Click to change the parent element value
        </Button>
      </div>
    );
  }
}

Copy code

Parent component

<EightteenChildOne name={'props Incoming name value'} eightteenChildOneToFather={(mode)=>this.eightteenChildOneToFather(mode)}></EightteenChildOne> 

// perhaps
<EightteenChildOne name={'props Incoming name value'} eightteenChildOneToFather={this.eightteenChildOneToFather.bind(this)}></EightteenChildOne> 
Copy code

When props transfers multiple values:
Traditional writing

const {dataOne,dataTwo,dataThree} = this.state
<Com dataOne={dataOne} dataTwo={dataTwo} dataThree={dataThree}>
Copy code

Upgrade writing

<Com {...{dataOne,dataTwo,dataThree}}>
Copy code

1.2 props upgrade

Principle: in the sub component, the method of the parent component is directly called by props to change the value of the parent component
Note: this method is almost the same as props, which is the application of props, so there is no example in the source code

Call the parent component method to change the value

// Parent component
state = {
  count: {}
}
changeParentState = obj => {
    this.setState(obj);
}
// Subassemblies
onClick = () => {
    this.props.changeParentState({ count: 2 });
}
Copy code

1.3 Provider,Consumer and Context

1. Before 16.x, context defines a global object, similar to vue's eventBus. If the component wants to use this value, it can be directly obtained through this.context

//Root component
class MessageList extends React.Component {
  getChildContext() {
    return {color: "purple",text: "item text"};
  }

  render() {
    const {messages} = this.props || {}
    const children = messages && messages.map((message) =>
      <Message text={message.text} />
    );
    return <div>{children}</div>;
  }
}

MessageList.childContextTypes = {
  color: React.PropTypes.string
  text: React.PropTypes.string
};

//Intermediate component
class Message extends React.Component {
  render() {
    return (
      <div>
        <MessageItem />
        <Button>Delete</Button>
      </div>
    );
  }
}

//Sub component (receiving component)
class MessageItem extends React.Component {
  render() {
    return (
      <div>
        {this.context.text}
      </div>
    );
  }
}

MessageItem.contextTypes = {
  text: React.PropTypes.string //React.PropTypes was abandoned in version 15.5. See the actual react version of the project
};

class Button extends React.Component {
  render() {
    return (
      <button style={{background: this.context.color}}>
        {this.props.children}
      </button>
    );
  }
}

Button.contextTypes = {
  color: React.PropTypes.string
};
Copy code

The context after 2.16.x uses the Provider and Customer modes, passing in the value in the top-level Provider, obtaining the value in the descendant level Consumer, and passing the function to modify the context to declare a global context definition. context.js

import React from 'react'
let { Consumer, Provider } = React.createContext();//Create context and expose the Consumer and Provider modes
export {
    Consumer,
    Provider
}
Copy code

Parent component import

// Import Provider
import {Provider} from "../../utils/context"

<Provider value={name}>
  <div style={{border:'1px solid red',width:'30%',margin:'50px auto',textAlign:'center'}}>
    <p>Value defined by parent component:{name}</p>
    <EightteenChildTwo></EightteenChildTwo>
  </div>
</Provider>
Copy code

Subassemblies

// Import Consumer
import { Consumer } from "../../utils/context"
function Son(props) {
  return (
    //The Consumer container can get the name attribute passed down above and display the corresponding value
    <Consumer>
      {name => (
        <div
          style={{
            border: "1px solid blue",
            width: "60%",
            margin: "20px auto",
            textAlign: "center"
          }}
        >
        // In Consumer, you can directly get the value of the parent component through name
          <p>Sub assembly. Get the value of the parent component:{name}</p>
        </div>
      )}
    </Consumer>
  );
}
export default Son;
Copy code

1.4 EventEmitter

EventEmitter portal Use the events plug-in to define a global event mechanism

1.5 route parameter transmission

1.params

<Route path='/path/:name' component={Path}/>
<link to="/path/2">xxx</Link>
this.props.history.push({pathname:"/path/" + name});
For reading parameters:this.props.match.params.name
 Copy code

2.query

<Route path='/query' component={Query}/>
<Link to={{ pathname : '/query' , query : { name : 'sunny' }}}>
this.props.history.push({pathname:"/query",query: { name : 'sunny' }});
For reading parameters: this.props.location.query.name
 Copy code

3.state

<Route path='/sort ' component={Sort}/>
<Link to={{ pathname : '/sort ' , state : { name : 'sunny' }}}> 
this.props.history.push({pathname:"/sort ",state : { name : 'sunny' }});
For reading parameters: this.props.location.query.state 
Copy code

4.search

<Route path='/web/search ' component={Search}/>
<link to="web/search?id=12121212">xxx</Link>
this.props.history.push({pathname:`/web/search?id ${row.id}`});
For reading parameters: this.props.location.search
 Copy code

There is a bug in react router DOM: v4.2.2. The parameter transfer jump page will be blank and will be loaded after refreshing

5. Advantages and disadvantages

1.params stay HashRouter and BrowserRouter The refresh page parameters in the route will not be lost
2.state stay BrowserRouter The refresh page parameter will not be lost in HashRouter The refresh page will be lost in the route
3.query: stay HashRouter and BrowserRouter The refresh page parameters in the route will be lost
4.query and state Can transfer objects
 Copy code

1.6 onRef

Principle: onRef communication principle is to pass this (component instance) of the component as a parameter to the parent component through the event mechanism of props, and the parent component can operate the state and method of the child component

EightteenChildFour.jsx

export default class EightteenChildFour extends React.Component {
  state={
      name:'This is a component EightteenChildFour of name value'
  }

  componentDidMount(){
    this.props.onRef(this)
    console.log(this) // ->Pass EightteenChildFour to the parent component this.props.onRef() method
  }

  click = () => {
    this.setState({name:'This is a component click Method change EightteenChildFour Altered name value'})
  };

  render() {
    return (
      <div>
        <div>{this.state.name}</div>
        <Button type="primary" onClick={this.click}>
          Click change component EightteenChildFour of name value
        </Button>
      </div>
    );
  }
}
Copy code

eighteen.jsx

<EightteenChildFour onRef={this.eightteenChildFourRef}></EightteenChildFour>

eightteenChildFourRef = (ref)=>{
  console.log('eightteenChildFour of Ref Value is')
  // The obtained ref includes the entire component instance
  console.log(ref)
  // Call subcomponent method
  ref.click()
}
Copy code

1.7 ref

Principle: get the whole sub component instance through the ref attribute of React, and then operate

EightteenChildFive.jsx

// Common component definition methods
export default class EightteenChildFive extends React.Component {
  state={
      name:'This is a component EightteenChildFive of name value'
  }

  click = () => {
    this.setState({name:'This is a component click Method change EightteenChildFive Altered name value'})
  };

  render() {
    return (
      <div>
        <div>{this.state.name}</div>
        <Button type="primary" onClick={this.click}>
          Click change component EightteenChildFive of name value
        </Button>
      </div>
    );
  }
}
Copy code

eighteen.jsx

// Hook get instance
componentDidMount(){
    console.log('eightteenChildFive of Ref Value is')
      // The obtained ref includes the entire component instance, and the sub component instance can also be obtained
    console.log(this.refs["eightteenChildFiveRef"])
  }

// Component definition ref attribute
<EightteenChildFive ref="eightteenChildFiveRef"></EightteenChildFive>
Copy code

1.8 redux

redux is an independent event communication plug-in, so I will not describe it here Please stamp the portal:

1.9 MobX

MobX is also an independent event communication plug-in, which will not be described here
Please stamp the portal:

1.10 flux

flux is also an independent event communication plug-in, so I will not describe it here
Please stamp the portal:

1.11 hooks

1.hooks uses userReducer and context to realize communication. The following is a simple redux simulation
2. Core files are divided into action, reducer and types
action.js

import * as Types from './types';

export const onChangeCount = count => ({
    type: Types.EXAMPLE_TEST,
    count: count + 1
})
Copy code

reducer.js

import * as Types from "./types";
export const defaultState = {
  count: 0
};
export default (state, action) => {
  switch (action.type) {
    case Types.EXAMPLE_TEST:
      return {
        ...state,
        count: action.count
      };
    default: {
      return state;
    }
  }
};
Copy code

types.js

export const EXAMPLE_TEST = 'EXAMPLE_TEST';
Copy code

eightteen.jsx

export const ExampleContext = React.createContext(null);//Create createContext context

// Define components
function ReducerCom() {
  const [exampleState, exampleDispatch] = useReducer(example, defaultState);

  return (
    <ExampleContext.Provider
      value={{ exampleState, dispatch: exampleDispatch }}
    >
      <EightteenChildThree></EightteenChildThree>
    </ExampleContext.Provider>
  );
}
Copy code

EightteenChildThree.jsx / / component

import React, {  useEffect, useContext } from 'react';
import {Button} from 'antd'

import {onChangeCount} from '../../pages/TwoTen/store/action';
import { ExampleContext } from '../../pages/TwoTen/eighteen';

const Example = () => {

    const exampleContext = useContext(ExampleContext);

    useEffect(() => { // Monitoring changes
        console.log('The change has been implemented')
    }, [exampleContext.exampleState.count]);

    return (
        <div>
            <p>Value is{exampleContext.exampleState.count}</p>
            <Button onClick={() => exampleContext.dispatch(onChangeCount(exampleContext.exampleState.count))}>Click add 1</Button>
        </div>
    )
}

export default Example;
Copy code

3.hooks actually encapsulates the original React API and exposes hooks that are convenient to use;

4. Hooks include:

Hook nameeffect
useStateInitialization and setting status
useEffectcomponentDidMount, componentDidUpdate and componentWillUnmount are combined, so you can listen for changes in the value defined by useState
useContextDefine a global object, similar to context
useReducerFunctions can be enhanced to provide Redux like functions
useCallbackThe memory function has two parameters. The first parameter is an anonymous function, which is the function body we want to create. The second parameter is an array. Each item in the array is used to determine whether the function body needs to be recreated. If the value of the passed variable remains unchanged, the memory result is returned. If any item is changed, a new result is returned
useMemoThe action and the passed in parameters are consistent with useCallback, which returns the function and useDemo returns the value
useRefGet the dom corresponding to the ref attribute
useImperativeMethodsCustomize the instance value exposed to the parent component when ref is used
useMutationEffectThe function is the same as useEffect, but before updating the sibling component, it is triggered synchronously at the same stage when React performs its DOM change
useLayoutEffectThe function is the same as useEffect, but it is triggered synchronously after all DOM changes

5.useImperativeMethods

function FancyInput(props, ref) {
  const inputRef = useRef();
  useImperativeMethods(ref, () => ({
    focus: () => {
      inputRef.current.focus();
    }
  }));
  return <input ref={inputRef} ... />;
}
FancyInput = forwardRef(FancyInput);
Copy code

1.12 slot

Slot is to transfer the label of the parent component to the child component, similar to the v-slot of vue
Scenario: some components only share some dom logic, some of which are independent

// Parent component file
import SlotChild from 'SlotChild'

<SlotChild
slot={<div>This is the parent component's slot</div>}>
</SlotChild>

// Subassemblies
 Direct acquisition of sub components this.props.slot The content can be obtained
 Copy code

1.13 comparison

methodadvantageshortcoming
propsNo need to introduce external plug-insBrother component communication needs to establish a common parent component, which is troublesome
props upgradeThere is no need to introduce external plug-ins, and the child is passed to the parent. There is no need to receive in the parent component with methodsSame as props
Provider,Consumer and ContextThere is no need to introduce external plug-ins, which is a communication tool across multi-level components or brother componentsStatus data: status tracking is troublesome
EventEmitterCan support brother, parent-child component communicationTo import an external plug-in:
Route parametersIt can support brother components to transfer values. The page is simple and the data transfer is very convenientCommunication between parent and child components is powerless
onRefYou can obtain the entire sub component instance, which is simple to useBrother component communication is troublesome, and it is not recommended to use officially
refSame as onRefSame as onRef
reduxA global state manager has been established, and brother parent-child communication can be solvedIntroduced external plug-ins
mobxA global state manager has been established, and brother parent-child communication can be solvedIntroduced external plug-ins
fluxA global state manager has been established, and brother parent-child communication can be solvedIntroduced external plug-ins
hooks16.x new content, can support brother, parent-child component communicationIt needs to be used together with context
slotSupport parent to child label transfer

Comparison of Redux, mobx and flux

methodintroduce
redux1. Core modules: Action,Reducer,Store;2. Store and change logic are separate; 3. There is only one Store;4. Single store with layered reducer; 5. There is no concept of scheduler; 6. The container components are connected; 7. The status cannot be changed; 8. More importantly, it follows the idea of functional programming
mobx1. Core modules: Action,Reducer,Derivation;2. There are multiple stores; 3. The design is more oriented towards object-oriented programming and responsive programming. Usually, the state is wrapped into observable objects. Once the state object changes, it can be automatically updated
flux1. Core modules: Store,ReduceStore,Container;2. There are multiple stores;

2.require.context()

This is the webpack api, which is introduced in Vue skills. Because Vue and react projects are packaged based on webpack, they can also be used in react

const path = require('path')
const files = require.context('@/components/home', false, /\.vue$/)
const modules = {}
files.keys().forEach(key => {
  const name = path.basename(key, '.vue')
  modules[name] = files(key).default || files(key)
})

Copy code

3.Decorator

Definition: decorator is a new feature of ES7, which can modify the properties of a class

import React from 'react'
import Test from '../../utils/decorators'

@Test
//As long as the Decorator is followed by Class, by default, Class has been passed into the Decorator as a parameter.
class TwentyNine extends React.Component{
    componentDidMount(){
        console.log(this,'decorator.js') // this here is an instance of a class
        console.log(this.testable)
    }
    render(){
        return (
            <div>This is skill 23</div>
        )
    }
}

export default TwentyNine
 Copy code

decorators.js

function testable(target) {
  console.log(target)
  target.isTestable = true;
  target.prototype.getDate = ()=>{
    console.log( new Date() )
  }
}

export default testable
 Copy code

Many middleware, such as redux, encapsulates the use of Decorator

4. Use if... else

Scenario: sometimes different contents need to be displayed according to different status value pages

import React from "react";

export default class Four extends React.Component {
  state = {
    count: 1
  };
  render() {
    let info
    if(this.state.count===0){
      info=(
        <span>This is a quantity of 0 displayed</span>
      )
    } else if(this.state.count===1){
      info=(
        <span>This is a quantity of 1 displayed</span>
      )
    }
    return (
      <div>
        {info}
      </div>
    );
  }
}
Copy code

5. Five ways to change the state value

Mode 1

let {count} = this.state
this.setState({count:2})
Copy code

Mode 2:callBack

this.setState(({count})=>({count:count+2}))
Copy code

Mode 3: receive state and props parameters

this.setState((state, props) => {
    return { count: state.count + props.step };
});
Copy code

Mode 4:hooks

const [count, setCount] = useState(0)
// Set value
setCount(count+2)
Copy code

Mode 5: called after the state value is changed

this.setState(
    {count:3},()=>{
        //Get the result do something
    }
)
Copy code

6. Listen for changes in states

Use componentWillReceiveProps before 1.16.x

componentWillReceiveProps (nextProps){
  if(this.props.visible !== nextProps.visible){
      //props value changes what you do
  }
}
Copy code

Note: sometimes componentWillReceiveProps will be triggered even if the props value does not change, because it will not be called after the first render in the life cycle, but will be called in each subsequent render = when the parent component transmits props again

Getderivedstatefromprops is used after 2.16.x, and componentWillReveiveProps is not removed after 16. X

export default class Six extends React.Component {
  state = {
    countOne:1,
    changeFlag:''
  };
  clickOne(){
    let {countOne} = this.state
    this.setState({countOne:countOne+1})
  };
  static getDerivedStateFromProps (nextProps){
    console.log('Change execution')
    return{
      changeFlag:'state Value change execution'
    }
  }
  render() {
    const {countOne,changeFlag} = this.state
    return (
      <div>
        <div>
         <Button type="primary" onClick={this.clickOne.bind(this)}>Click add 1</Button><span>countOne Value is{countOne}</span>
        <div>{changeFlag}</div>
        </div>
      </div>
    );
  }
}
Copy code

7. Component definition method

Method 1: Function definition of Es5

function FunCom(props){
  return <div>This is Function Defined components</div>
}
ReactDOM.render(<FunCom name="Sebastian" />, mountNode)

// Before hooks came out, this was the method to define stateless components. Now hooks can also handle states
 Copy code

Method 2: createClass definition of Es5

const CreateClassCom = React.createClass({
  render: function() {
  return <div>This is React.createClass Defined components</div>
  }
});
Copy code

Mode 3: Extensions of ES6

class Com extends React.Component {
  render(){
    return(<div>This is React.Component Defined components</div>)
  }
}
Copy code

call

export default class Seven extends React.Component {
  render() {
    return (
      <div>
        <FunCom></FunCom>
        <Com></Com>
      </div>
    );
  }
}
Copy code

Difference: the createClass of ES5 is created by using the function to simulate the class writing method of es6; The component created by adding the attribute of class in es6 is simple to create

8. Get component through ref attribute

Mode 1: also the earliest usage, through this Refs [property name acquisition] can also be applied to the component to obtain the component instance

class RefOne extends React.Component{
  componentDidMount() {
    this.refs['box'].innerHTML='This is div Box,adopt ref obtain'
  }
  render(){
    return(
      <div ref="box"></div>
    )
  }
}
Copy code

Mode 2: callback function. Mount the function on the dom node or component. The input parameter of the function is the dom node or component instance. The effect is the same as that of the string form, and the reference is obtained

class RefTwo extends React.Component{
  componentDidMount() {
    this.input.value='This is the default value of the input box';
    this.input.focus();
  }
  render(){
    return(
      <input ref={comp => { this.input = comp; }}/>
    )
  }
}
Copy code

Mode 3: react Createref() after react version 16.3, use this method to create Ref. Assign it to a variable and mount it on the dom node or component through Ref. the current attribute of the ref will get the instance of the dom node or component

class RefThree extends React.Component{
  constructor(props){
    super(props);
    this.myRef=React.createRef();
  }
  componentDidMount(){
    console.log(this.myRef.current);
  }
  render(){
    return <input ref={this.myRef}/>
  }
}
Copy code

Method 4:React.forwardRef
Provided after React 16.3, it can be used to create subcomponents to pass ref

class RefFour extends React.Component{
  constructor(props){
    super(props);
    this.myFourRef=React.forwardRef();
  }
  componentDidMount(){
    console.log(this.myFourRef.current);
  }
  render(){
    return <Child ref={this.myFourRef}/>
  }
}
Copy code

The subcomponents pass through react forwardRef can be passed to internal nodes or components to realize cross level reference. forwardRef can obtain the instance of the original component in the high-level component This function will be emphasized in skill 18

9.static use

Scenario: a keyword that declares a static method. A static method means that it can be called directly even if there is no component instance

export default class Nine extends React.Component {
  static update(data) {
    console.log('The static method call is executed')
  }
  render() {
    return (
      <div>
        This is static Keyword skills
      </div>
    );
  }
}

Nine.update('2')
Copy code

Note: 1. In ES6 class, when we define a component, we usually define a class, while static creates an attribute or method belonging to this class
2. The component is an instance of this class. The props and state of the component belong to this instance, so the instance has not been created
3. Therefore, static is not defined by react, and adding the static keyword means that the method will not be inherited by the instance, but will be called directly through the class, so this is also inaccessible
4.getDerivedStateFromProps also listens to the value through the static method. Please refer to skill 6 for details

10.constructor and super

Review:
1. Before talking about these two attributes, first review the ES6 function definition method
2. Every class defined in class mode has a constructor function by default. This function is the main function of the constructor, and this inside the function body points to the generated instance
3.super keyword is used to access and call functions on the parent object of an object

export default class Ten extends React.Component {
  constructor() { // Main function of class
    super() // React.Component.prototype.constructor.call(this) is actually to get the properties and methods of the parent class
    this.state = {
      arr:[]
    }
  }  
  render() {
    return (
      <div>
        This is trick 10
      </div>
    );
  }
}
Copy code

11.PropTypes

Scenario: detecting the data type of the incoming sub component
Type checking PropTypes has been deprecated since React v15.5, please use prop types
Mode 1: old writing

class PropTypeOne extends React.Component {
  render() {
    return (
      <div>
        <div>{this.props.email}</div>
        <div>{this.props.name}</div>
      </div>
    );
  }
}

PropTypeOne.propTypes = {
  name: PropTypes.string, //Values can be array,bool,func,number,object,symbol
  email: function(props, propName, componentName) { //Custom verification
    if (
      !/^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])+/.test(
        props[propName]
      )
    ) {
      return new Error(
        "assembly" + componentName + "Properties in" + propName + "Does not conform to the format of the mailbox"
      );
    }
  },
};
Copy code

Method 2: use the static attribute keyword static of ES7

class PropTypeTwo extends React.Component {
  static propTypes = {
      name:PropTypes.string
  };
  render() {
    return (
      <div>
        <div>{this.props.name}</div>
      </div>
    );
  }
}
Copy code

12. Use class field declaration syntax

Scenario: you can initialize the local state without using the constructor, and declare the class methods by using the arrow function without binding them additionally

class Counter extends Component {
  state = { value: 0 };

  handleIncrement = () => {
    this.setState(prevState => ({
      value: prevState.value + 1
    }));
  };

  handleDecrement = () => {
    this.setState(prevState => ({
      value: prevState.value - 1
    }));
  };

  render() {
    return (
      <div>
        {this.state.value}

        <button onClick={this.handleIncrement}>+</button>
        <button onClick={this.handleDecrement}>-</button>
      </div>
    )
  }
}
Copy code

13. Asynchronous components

1. Scenario: route switching. If multiple pages are loaded synchronously, the route will be slow

2. Core API:
loader: components to be loaded
loading: page display component not loaded
Delay: delay loading time
Timeout: timeout

3. Use method:
Install react loadable and install syntax dynamic import for Babel plug-in React loadable is implemented through asynchronous import of webpack

const Loading = () => {
  return <div>loading</div>;
};

const LoadableComponent = Loadable({
  loader: () => import("../../components/TwoTen/thirteen"),
  loading: Loading
});

export default class Thirteen extends React.Component {
  render() {
    return <LoadableComponent></LoadableComponent>;
  }
}
Copy code

4.Loadable.Map()
Load high-level components of multiple resources in parallel

14. Dynamic components

Scenario: dynamic loading of components will be involved in a tab switch
In essence, it uses ternary expressions to determine whether the component is displayed

class FourteenChildOne extends React.Component {
    render() {
        return <div>This is dynamic component 1</div>;
    }
}

class FourteenChildTwo extends React.Component {
    render() {
        return <div>This is dynamic component 2</div>;
    }
}

export default class Fourteen extends React.Component {
  state={
      oneShowFlag:true
  }
  tab=()=>{
      this.setState({oneShowFlag:!this.state.oneShowFlag})
  }
  render() {
    const {oneShowFlag} = this.state
    return (<div>
        <Button type="primary" onClick={this.tab}>Display components{oneShowFlag?2:1}</Button>
        {oneShowFlag?<FourteenChildOne></FourteenChildOne>:<FourteenChildTwo></FourteenChildTwo>}
    </div>);
  }
}
Copy code

If it is a single component, can short circuit operation be used

oneShowFlag&&<FourteenChildOne></FourteenChildOne>
Copy code

15. Recursive component

Scene: tree component
Using react Fragment or div package cycle

class Item extends React.Component {
  render() {
    const list = this.props.children || [];
    return (
      <div className="item">
        {list.map((item, index) => {
          return (
            <React.Fragment key={index}>
              <h3>{item.name}</h3>
              {// When the node has children, the recursive call itself
              item.children && item.children.length ? (
                <Item>{item.children}</Item>
              ) : null}
            </React.Fragment>
          );
        })}
      </div>
    );
  }
}
Copy code

16. Controlled and uncontrolled components

Controlled component: the state of the component is controlled by the state value state or props of React

class Controll extends React.Component {
  constructor() {
    super();
    this.state = { value: "This is the default value for controlled components" };
  }
  render() {
    return <div>{this.state.value}</div>;
  }
}
Copy code

Uncontrolled component: the component is not controlled by the state value of React. It is controlled by the dom property or the ref of React

class NoControll extends React.Component {
  render() {
    return <div>{this.props.value}</div>;
  }
}
Copy code

Import Code:

export default class Sixteen extends React.Component {
  componentDidMount() {
    console.log("ref The value of the uncontrolled component obtained is:", this.refs["noControll"]);
  }
  render() {
    return (
      <div>
        <Controll></Controll>
        <NoControll
          value={"This is the value passed in by an uncontrolled component"}
          ref="noControll"
        ></NoControll>
      </div>
    );
  }
}
Copy code

17. High order components (HOCs)

17.1 definitions

1. It is similar to the definition of high-order function, and takes a component as a parameter or returns a component;
2. Function:
Extract duplicate code, realize component reuse, common scenarios, and page reuse;
Conditional rendering, control the rendering logic of components (rendering hijacking), common scenes, and permission control;
Capture / hijack the life cycle of the processed component, common scenarios, component rendering performance tracking and log management

17.2 implementation method

1. Attribute agent

import React,{Component} from 'react';

const Seventeen = WrappedComponent =>
  class extends React.Component {
    render() {
      const props = {
        ...this.props,
        name: "This is a high-order component"
      };
      return <WrappedComponent {...props} />;
    }
  };

class WrappedComponent extends React.Component {
  state={
     baseName:'This is the basic component' 
  }
  render() {
    const {baseName} = this.state
    const {name} = this.props
    return <div>
        <div>The value of the basic component is{baseName}</div>
        <div>The value obtained by the high-level component attribute proxy is:{name}</div>
    </div>
  }
}

export default Seventeen(WrappedComponent)
Copy code

2. Reverse inheritance
The principle is to use super to change the this direction of the component, and then some values of the container component can be processed in the component

  const Seventeen = (WrappedComponent)=>{
    return class extends WrappedComponent {
        componentDidMount() {
            this.setState({baseName:'This is the base component name modified through reverse inheritance'})
        }
        render(){
            return super.render();
        }
    }
}

class WrappedComponent extends React.Component {
  state={
     baseName:'This is the basic component' 
  }
  render() {
    const {baseName} = this.state
    return <div>
        <div>The value of the basic component is{baseName}</div>
    </div>
  }
}

export default Seventeen(WrappedComponent);
Copy code

18. Whether the element is displayed

Generally, ternary expression is used

 flag?<div>show contents</div>:''
 flag&&<div>show contents</div>
Copy code

19.Dialog component creation

Dialog should be a component that is used more frequently. There are three different ways to create dialog: 1. Control whether the component is displayed through state

 class NineteenChildOne extends React.Component {
  render() {
    const Dialog = () => <div>This is layer 1</div>;

    return this.props.dialogOneFlag && <Dialog />;
  }
}
Copy code

Method 2: create elastic layer through ReactDom.render - mount the outer layer of the root node
Control the display and hiding of elements through the native createElement,appendChild, removeChild and react's ReactDOM.render,ReactDOM.unmountComponentAtNode

NineteenChild.jsx

import ReactDOM from "react-dom";

class Dialog {
  constructor(name) {
    this.div = document.createElement("div");
    this.div.style.width = "200px";
    this.div.style.height = "200px";
    this.div.style.backgroundColor = "green";
    this.div.style.position = "absolute";
    this.div.style.top = "200px";
    this.div.style.left = "400px";
    this.div.id = "dialog-box";
  }
  show(children) {
    // Destroy
    const dom = document.querySelector("#dialog-box");
    if(!dom){ //Compatible with multiple clicks
      // display
      document.body.appendChild(this.div);
      ReactDOM.render(children, this.div);
    }
  }
  destroy() {
    // Destroy
    const dom = document.querySelector("#dialog-box");
    if(dom){//Compatible with multiple clicks
      ReactDOM.unmountComponentAtNode(this.div);
      dom.parentNode.removeChild(dom);
    }
  }
}
export default {
  show: function(children) {
    new Dialog().show(children);
  },
  hide: function() {
    new Dialog().destroy();
  }
};
Copy code

nineteen.jsx

twoSubmit=()=>{
    Dialog.show('This is layer 2')
  }

  twoCancel=()=>{
    Dialog.hide()
  }
Copy code

20.React.memo

Function: when the input properties of class components are the same, you can use pureComponent or shouldComponentUpdate to avoid component rendering. Now, you can wrap the function component in react Memo to achieve the same function

import React from "react";

function areEqual(prevProps, nextProps) {
  /*
  If nextProps is passed into the render method, the returned result is the same as
  If the return results of prevProps passed into the render method are consistent, it returns true,
  Otherwise, it returns false
  */
  if (prevProps.val === nextProps.val) {
    return true;
  } else {
    return false;
  }
}

// React.memo() has two parameters, the first is a pure function and the second is a comparison function
export default React.memo(function twentyChild(props) {
  console.log("MemoSon rendered : " + Date.now());
  return <div>{props.val}</div>;
}, areEqual);
Copy code

21.React.PureComponent

effect:
1.React.PureComponent is similar to React.Component in that both define a component class.
2. The difference is react Component does not implement shouldComponentUpdate(), but React.PureComponent implements it by shallow comparison of props and state.
3.React.PureComponent is used in the class, and React.memo is used in the function.
4. If the props and state of the component are the same and the content of the render is the same, then React.PureComponent can be used to improve the performance of the component

class TwentyOneChild extends React.PureComponent{  //Component directly inherits React.PureComponent
  render() {
    return <div>{this.props.name}</div>
  }
}

export default class TwentyOne extends React.Component{
    render(){
        return (
            <div>
              <TwentyOneChild name={'This is React.PureComponent How to use'}></TwentyOneChild>
            </div>
        )
    }
}
Copy code

22.React.Component

Function: it is a react component based on ES6 class. React allows you to define a class or function as a component. To define a component class, you need to inherit React.Component

export default class TwentyTwo extends React.Component{ //Component definition method
    render(){
        return (
            <div>This is skill 22</div>
        )
    }
}
Copy code

23. Print false value in JSX

definition:
1. False value (virtual value) is a value recognized as false in the Boolean context;
2. The values are 0, '', '', '' ` `, null,undefined,NaN

export default class TwentyThree extends React.Component{
    state={myVariable:null}
    render(){
        return (
            <div>{String(this.state.myVariable)}</div>
        )
    }
}
Copy code

If the virtual value is directly displayed, it will be implicitly converted to false, so the page will not be displayed

24.ReactDOM.createPortal

Function: the element returned by the render function of the component will be mounted on its parent component. createPortal provides an excellent scheme for rendering child nodes to DOM nodes other than the parent component

import React from "react";
import ReactDOM from "react-dom";
import {Button} from "antd"

const modalRoot = document.body;

class Modal extends React.Component {
  constructor(props) {
    super(props);
    this.el = document.createElement("div");
    this.el.style.width = "200px";
    this.el.style.height = "200px";
    this.el.style.backgroundColor = "green";
    this.el.style.position = "absolute";
    this.el.style.top = "200px";
    this.el.style.left = "400px";
  }

  componentDidMount() {
    modalRoot.appendChild(this.el);
  }

  componentWillUnmount() {
    modalRoot.removeChild(this.el);
  }

  render() {
    return ReactDOM.createPortal(this.props.children, this.el);
  }
}

function Child() {
  return (
    <div className="modal">
      This is through ReactDOM.createPortal Created content
    </div>
  );
}

export default class TwentyFour extends React.Component {
  constructor(props) {
    super(props);
    this.state = { clicks: 0 };
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    this.setState(prevState => ({
      clicks: prevState.clicks + 1
    }));
  }

  render() {
    return (
      <div>
          <Button onClick={this.handleClick}>Click add 1</Button>
        <p>Number of clicks: {this.state.clicks}</p>
        <Modal>
          <Child />
        </Modal>
      </div>
    );
  }
}

Copy code

In this way, the element is appended to the specified element

25. Use innerHTML in React

Scenario: some background return fields are in html format, so innerHTML attribute needs to be used

export default class TwentyFive extends React.Component {
  render() {
    return (
      <div dangerouslySetInnerHTML={{ __html: "<span>This is rendered HTML content</span>" }}></div>
    );
  }
}
Copy code

26.React.createElement

Syntax:
React.createElement( type, [props], [...children] )

Source code:

export default class TwentySix extends React.Component {
  render() {
    return (
      <div>
        {React.createElement(
          "div",
          { id: "one", className: "two" },
          React.createElement("span", { id: "spanOne" }, "This is the first span label"),
          React.createElement("br"),
          React.createElement("span", { id: "spanTwo" }, "This is the second one span label")
        )}
      </div>
    );
  }
}
Copy code

Principle: in fact, the dom of JSX is finally converted into js, which is React.createElement

// jsx syntax
<div id='one' class='two'>
    <span id="spanOne">this is spanOne</span>
    <span id="spanTwo">this is spanTwo</span>
</div>

// Convert to js
React.createElement(
  "div",
 { id: "one", class: "two" },
 React.createElement( "span", { id: "spanOne" }, "this is spanOne"), 
 React.createElement("span", { id: "spanTwo" }, "this is spanTwo")
);
Copy code

27.React.cloneElement

Syntax:

React.cloneElement(
  element,
  [props],
  [...children]
)
Copy code

Function: this method is used to copy components, pass values to components or add properties
Core code

React.Children.map(children, child => {
  return React.cloneElement(child, {
    count: _this.state.count
  });
});
Copy code

28.React.Fragment

Function: React.Fragment allows you to aggregate a list of child elements without adding additional nodes in the DOM
Core code

render() {
    const { info } = this.state;
    return (
      <div>
        {info.map((item, index) => {
          return (
            <React.Fragment key={index}>
              <div>{item.name}</div>
              <div>{item.age}</div>
            </React.Fragment>
          );
        })}
      </div>
    );
  }
Copy code

29. Cycle element

Instead of encapsulating the v-for instruction in vue, it traverses through the map

{arr.map((item,index)=>{
  return(
    <div key={item.id}>
      <span>{item.name}</span>
      <span>{item.age}</span>
    </div>
  )
})}
Copy code

30. Set and get custom properties for DOM

Function: some values need to be passed through custom attributes

export default class Thirty extends React.Component {
  click = e => {
    console.log(e.target.getAttribute("data-row"));
  };

  render() {
    return (
      <div>
        <div data-row={"Attribute 1"} data-col={"Attribute 2"} onClick={this.click}>
          Click to get properties
        </div>
      </div>
    );
  }
}
Copy code

31. Binding event

Scenario: the interaction will involve event clicking, and then clicking the selected value to pass parameters is also a very common scenario

import React from "react";
import { Button } from 'antd'

export default class Three extends React.Component {
  state = {
    flag: true,
    flagOne: 1
  };
  click(data1,data2){
    console.log('data1 Value is',data1)
    console.log('data2 Value is',data2)
  }
  render() {
    return (
      <div>
        <Button type="primary" onClick={this.click.bind(this,'Parameter 1','Parameter 2')}>Click event</Button>
      </div>
    );
  }
}

Copy code

Use the method in the source code routes JS is used in detail

32.React-Router

32.1 difference between V3 and V4

1. In V3 or earlier versions of V, router and layout components are separated;
2.V4 is a centralized router. Through Route nesting, layout and page nesting are realized. Layout and page components are part of the router;
3. The routing rule in V3 is exclusive, which means that only one route is finally obtained;
4. Routes in V4 are inclusive by default, which means multiple; Can match and render at the same time If you want to match only one route, you can use Switch. Only one of the routes will be rendered. At the same time, you can add exact to each route to achieve accurate match Redirect and browser redirection. When many routes do not match, you can match them

32.2 use

import { HashRouter as Router, Switch  } from "react-router-dom";

class App extends React.Component{
    render(){
        const authPath = '/login' // The default page returned when you are not logged in can be set by yourself
        let authed = this.props.state.authed || localStorage.getItem('authed') // After logging in, you can use redux to modify this value
        return (
            <Router>
                <Switch>
                    {renderRoutes(routes, authed, authPath)}
                </Switch>
            </Router>
        )
    }
}
Copy code

In V4, Layout and page nesting are realized through Route nesting, and Switch switches routes

33. Style introduction method

Method 1:import

import './App.css';
Copy code

Mode 2: inline mode

import React from 'react';

const Header = () => {

    const heading = 'Head assembly'

    return(
        <div style={{backgroundColor:'orange'}}>
            <h1>{heading}</h1>
        </div>
    )
}

perhaps
import React from 'react';

const footerStyle = {
    width: '100%',
    backgroundColor: 'green',
    padding: '50px',
    font: '30px',
    color: 'white',
    fontWeight: 'bold'
}

export const Footer = () => {
    return(
        <div style={footerStyle}>
            Bottom assembly
        </div>
    )
}
Copy code

34. Dynamically bind className

Principle: control className value through ternary expression

render(){
  const flag=true
  return (
    <div className={flag?"active":"no-active"}>This is skill 34</div>
  )
}
Copy code

summary

These are the 34 skills of React summarized from the actual project development;

Tags: Javascript Front-end React

Posted by exasp on Sat, 13 Aug 2022 21:46:54 +0530