Introduction of the React Hooks

React Hooks replace inherited classes with functions and use prefunctions to manage state. Use the Hooks to define components that do not use classes. Components are divided into stateful components and stateless components. Stateful components are declared as classes, while stateless components are declared as functions. Now all components can be declared as functions.

Using the step

Create a project using create-react-app

npm create-react-app i -g ## Install scaffolding

create-react-app [deom_name] ## Create projectCreating a new React app in D:\Learning_code\06_ Advanced Frameworks & Techniques \react-hooks \react-hooks. CNPM I [email protected] [email protected] --save## Update
Copy the code

Class component writing

import React, { Component } from 'react';
class Example extends Component {
    constructor(props) {
        super(props);
        this.state = { count:0}}render() { 
        return (<>
            <p>You clicked {this.state.count} times</p>
            <button onClick={this.addCount.bind(this)}>Chlick me</button>
        </>);
    }
    addCount(){ // Each increment requires access to this.state
        this.setState({count:this.state.count+1}}})export default Example;
Copy the code

Hooks writing

import React, { useState } from 'react';
function CountHooks(){
    const [ count , setCount ] = useState(0);
    return (<>
        <p>You clicked {count} times</p>
        <button onClick={()= >{setCount(count+1)}}>click me</button>
    </>)}export default CountHooks;
Copy the code

Must be defined in the root function

import React, { useState } from 'react';
let showSex = true
function Example(){
    // Declare the count state, accept the value and the method to set the value
    const [ age, setAge ] = useState(18);
    if (showSex) { / / an error
        const [ sex, setSex ] = useState('male');
        showSex = false;
    }
    const [ work, setWork ] = useState('Front End Engineer');
    return (<>
        <p>Mr_Mao year: {age}</p>
        <p>Gender: {sex}</p>
        <p>The work is: {work}</p>
    </>)}export default Example;
Copy the code

UseEffect A hook that declares the lifecycle

In the case of React Hooks, we can use useEffect to implement the lifecycle effects of the above code.

import React, { useState, useEffect } from 'react';
function CountHooks(){
    const [ count, setCount ] = useState(0);
    //-- key code ---------start-------
    useEffect(() = >{
        console.log(`useEffect=>You clicked ${count} times`)})//-- key code ---------end-------
    return (<>
        <p>You clicked {count} times</p>
        <button onClick={()= >{setCount(count+1)}}>click me</button>
    </>)}export default CountHooks;
Copy the code

React calls the useEffect function for the first rendering and every subsequent rendering. UseEffectuseEffect does not prevent the browser from updating the view, so these functions are executed asynchronously. The code in componentDidMonut and componentDidUpdate is executed synchronously.

UseEffect When a component is removed

Every time a component is updated, an attempt is made to remove the return function from the previous useEffect.

import React, { useState, useEffect } from 'react';
function CountHooks(){
    const [ count, setCount ] = useState(0);
    //-- key code ---------start-------
    useEffect(() = >{
        console.log(`useEffect=>You clicked ${count} times`)
        return () = >{
            // Returns a side effect unbinding function}})//-- key code ---------end-------
    return (<>
        <p>You clicked {count} times</p>
        <button onClick={()= >{setCount(count+1)}}>click me</button>
    </>)}export default CountHooks;
Copy the code

UseEffect also has a second array parameter that specifies the list of states to listen on. By default, this parameter should be fully listened. Explicitly providing an empty array does not perform this “side effect” every time a component is updated.

useEffect(() = >{
	console.log(`useEffect=>You clicked ${count} times`)
	return () = >{/* Execute */ when the component is destroyed}
}, [])
useEffect(() = >{
	console.log(`useEffect=>You clicked ${count} times`)
	return () = >{/* when count changes */}
}, [count])
Copy the code

UseContext defines component parameters

Passed in parent components, using createContext and useContext to pass parent parameters

import React, { useState, createContext, useContext } from 'react';
// Create count context
const CountContext = createContext()
/ / child component
function Counter() {
    let count = useContext(CountContext)
    return <h2>{count}</h2>
}
/ / the parent component
function CountHooks() {
    const [count, setCount] = useState(0);
    return (
        <div>
            <p>You clicked {count} times</p>
            <button onClick={()= > { setCount(count + 1) }}>click me</button>{/* Create a context component, value holds the value that needs to be passed, pass the component in the tag */}<CountContext.Provider value={count}>
                <Counter />
            </CountContext.Provider>
        </div>)}export default CountHooks;
Copy the code

UseReducer status library definition

import React, { useReducer } from 'react';
function ReducerDemo() {
    The useReducer parameter is the Reducer state function and the second parameter is the default value of the state
    const [count, dispatch] = useReducer((state, action) = > {
        switch (action) {
            case 'add':
                return state + 1
            case 'sub':
                return state - 1
            default: returnstate; }},0)
    return <>
        <div>
            <h2>Now the score is {count}</h2>{/* Click to distribute, change the state of count */}<button onClick={()= > dispatch('add')}>Increment</button>
            <button onClick={()= > dispatch('sub')}>Decrement</button>
        </div>
    </>
}
export default ReducerDemo
Copy the code

Reducer and Context achieve global state management

The useReducer mainly implements state management and adopts Reducer mode management. Context mainly implements data transfer in multiple components. Together, the two can achieve a global state data management.

import React, { createContext, useReducer } from 'react'
// Define a global context component
export const ColorContext = createContext({})
// Define an action constant to change the state
export const UPDATE_COLOR = "UPDATE_COLOR"
// Define a pure function Reducer state library
const reducer = (state,action) = >{
    switch(action.type){
        case UPDATE_COLOR:
            return action.color
        default:
            return state
    }
}
export const Color = props= > {
    const [color, dispatch] = useReducer(reducer, "blue")
    return <>{/* Pass in an object in the global context, which can be used by each component in the global useContext reference */} {/* Pass in a state and distribution method defined by useReducer, form a state library that can be seen and called globally */}<ColorContext.Provider value={{ color.dispatch}} >
            {props.children}
        </ColorContext.Provider>
    </>
}
Copy the code

UseMemo addresses rendering performance issues

UseMemo is primarily designed to address performance issues with useless rendering using React hooks. Using function to declare components loses the shouldCompnentUpdate (before component updates) lifecycle, which means there is no way to determine whether a component is updated by a condition before component updates. Moreover, the mount and update states are no longer distinct in function components, which means that every call to a function component executes all the internal logic, resulting in a significant performance penalty.

import React, { useState, useMemo } from 'react';
function Example() {
    const [xiaohong, setXiaohong] = useState('Xiaohong hospitality status')
    const [zhiling, setZhiling] = useState('Zhiling Hospitality status')
    return <>
        <button onClick={()= >{setXiaohong(new Date().getTime())}}> small red</button>
        <button onClick={()= >{setZhiling(new Date().getTime() + ')}}</button>
        <ChildComponent name={xiaohong}>{zhiling}</ChildComponent>
    </>
}
function ChildComponent({ name, children }) {
    function changeXiaohong(name) {
        console.log('Here she comes, here she comes. Little Red is coming to us. ')
        return name + 'Here comes Red.'
    }
    // This method is executed whenever the state of the parent component changes, which can cause performance problems
    const actionXiaohong = changeXiaohong(name)
    return <>
        <div>{actionXiaohong}</div>
        <div>{children}</div>
    </>
}

export default Example
Copy the code

In this case, you will find that when you click the zhiling button in the browser, the method corresponding to the red will be executed. Although the result is the same, it will be executed every time. This is the performance loss. Currently there are only sub-components and the business logic is very simple, which can have serious consequences if it is a background query. So the problem has to be solved.

In fact, as long as you use useMemo, and then pass her the second parameter, the match is successful, will be executed. The code is as follows:

function ChildComponent({name,children}){
    function changeXiaohong(name){
        console.log('Here she comes, here she comes. Little Red is coming to us. ')
        return name+'Here comes Red.'
    }
    const actionXiaohong = useMemo(() = >changeXiaohong(name),[name]) 
    return (
        <>
            <div>{actionXiaohong}</div>
            <div>{children}</div>
        </>)}Copy the code

Click the zhiling button in the browser at this time, changeXiaohong is no longer executed. It also saves performance costs. See the role of optimization from the program itself. Good programmers will continue to optimize their own programs, such unnecessary performance waste is absolutely not allowed, so the use of useMemo in the work or more.

UseRef retrieves the DOM element

UseRef isn’t used much, but it’s not missing. It has two main functions: Use useRef to retrieve DOM elements in React JSX. Once you retrieve them, you can control anything in the DOM. However, this is not recommended. The React interface changes can be controlled by state. Or you can use useRef to save variables, which we don’t use much in our work, but we have useContext and it doesn’t make a lot of sense, but it’s learning, and I’ll talk about it too.

import React, { useRef, useState, useEffect } from 'react';
function Example8() {
    const inputEl = useRef(null)
    const onButtonClick = () = > {
        inputEl.current.value = "Hello ,useRef"
        console.log(inputEl)
    }
    //----------- key code --------start
    const [text, setText] = useState('jspang')
    const textRef = useRef()

    useEffect(() = > {
        textRef.current = text;
        console.log('textRef.current:', textRef.current)
    })
    //---------- key code --------------end
    return <>{/* Save input ref to inputEl */}<input ref={inputEl} type="text" />
        <button onClick={onButtonClick}>Display text on input</button>
        <br />
        <br />
        <input value={text} onChange={(e)= > { setText(e.target.value) }} />
    </>

}
export default Example8
Copy the code

At this point, each state change can be implemented and saved to useRef. That’s what we call saving variables. The main function of useRef is to get the DOM and save variables.

Custom hooks functions

In fact, custom Hooks functions are similar to building components using Hooks. They are almost the same as writing functions in JavaScript, except that they have some React Hooks. Custom Hooks function for functionality, components for interface and business logic. Since there is not much difference, it is also very casual to use. This is fine if the project is small, but if the project is complex enough, the structure of the project is not clear. So it’s important to learn about custom Hooks functions.

In the actual development, in order to interface more beautiful. Getting the size of the browser window is a frequently used function, so that frequently used functions can be wrapped in a custom Hooks function. Remember to start with use to distinguish between components and custom functions.

Write a method onResize that changes the state each time. This method uses useCallback to cache methods (useMemo is used to cache variables).

import React, { useState ,useEffect ,useCallback } from 'react';
function useWinSize(){
    const [ size , setSize] = useState({
        width:document.documentElement.clientWidth,
        height:document.documentElement.clientHeight
    })
    const onResize = useCallback(() = >{
        setSize({
            width: document.documentElement.clientWidth,
            height: document.documentElement.clientHeight
        })
    },[]) 
    useEffect(() = >{
        window.addEventListener('resize',onResize)
        return () = >{
            window.removeEventListener('resize',onResize)
        }
    },[])
    return size;
}
function Example9(){
    const size = useWinSize()
    return <div>Page Size: {Size. Width} {x the Size, height}</div>
}
export default Example9 
Copy the code