React Hook - use these 9 hooks to be invincible

React Hook guide

What is Hook?

Hook is a new feature of React 16.8. It allows you to use state and other React features without writing class es.

Hook is essentially a function. It simplifies components and has its own state management, life cycle management and state sharing.

useState useEffect useContext useReducer

What did Hook solve?

State reuse between components. For example, using useContext can solve the problem of state reuse, or customizing Hook to customize the state management in line with your business scenario. The use of life cycle in functional components can better design and encapsulate components. The life cycle cannot be used directly in function components. Hook solves this problem well. The differences between function components and class components also need to distinguish the use scenarios of the two components. Using Hook doesn't need to think about this at all. It can use more new features of React.

When to use Hook?

Called at the top level of a function component

Use in function / use in custom Hook

Hook built in React

useState state management useEffect lifecycle management useContext shared status data useMemo cache value useRef get Dom operation useCallback cache function Usereducer is similar to redux useImperativeHandle subcomponent exposure value / method useLayoutEffect completes the side effect operation, which will block the browser drawing

useState state management

In the class component, we get the state through this State.

In the function component, there is no this. We can use the useState provided by Hook to manage and maintain the state

useState definition / use

const [state, setState] = useState(initialState)

setState is the update sate method Usestate (initialstate) initialstate is the initial value

Intact chestnuts

import {useState} from 'react';

export default () => {
    const [data, setData] = useState('WeChat official account: front-end self learning community')
    return (
        <div>
            <h1>{data}</h1>
            {/* Update state */}
            <button onClick={()=>{setData('WeChat official account: front end self learning community 666')}}></button>
        </div>
    )
}

useEffect lifecycle management

definition

useEffect can be regarded as the life cycle management of functional components.

Because the life cycle cannot be used directly in functional components, you must host hooks for management and use.

There are three lifecycle functions that useEffect can use:

componentDidmount componentDidUpdate componentWillUnmount

No need to clear Effect usage

What is use without clearing Effect?

After React updates the DOM, run some additional code, which is executed in the compoentdidcount and componentUpdate of the life cycle.

    useEffect(() => {
        //It will be executed by default  
        // This is equivalent to the class component life cycle
        //compoentDidmount    compoentDidUpdate
    }, [])

Clear Effect usage

1. What is clear Effect?

When a component needs to be unloaded and some event processing needs to be performed, the componentUnmount of the class component life cycle needs to be used It is easy to use in useEffect. Just return a method internally and write the corresponding business logic in the method

2. Why return a function in Effect?

This is an optional cleanup mechanism for effect. Each effect can return a cleanup function. This brings together the logic for adding and removing subscriptions. They are all part of the effect.

    useEffect(()=>{
        return () => {
            console.log('Execute on component uninstall')
        }
    })

Monitor state changes

The corresponding business logic can be realized by controlling and monitoring the change of state.

    useEffect(() => {
        // Monitor num and count status changes
        // Null [] or not write when not listening
    }, [num, count])

Intact chestnuts

import { useState, useEffect } from 'react';

export default () => {
    const [num, setNum] = useState(0)
    const [count, setCount] = useState(1)

    useEffect(() => {
        //It will be executed by default  
        // This is equivalent to the compoentDidmount compoentDidUpdate of the class component life cycle
        console.log(`num: ${num}`)
        console.log(`count: ${count}`)

        // When the component is unloaded, the contents in return will be executed
        return () => {
            // componentWillUnMount equivalent to the class component life cycle 
            console.log('test')
        }
    }, [num])

    return (
        <div>
            <h1>{num}</h1>
            <button onClick={() => { setNum(num + 1) }}> to update Num</button>
            <hr />
            <h1>{count}</h1>
            <button onClick={() => { setCount(count + 1) }}> to update Count</button>
        </div>
    )
}

useRef

What is useRef?

useRef returns a variable ref object whose property current is initialized to the passed in parameter (initialValue). The returned ref object remains unchanged throughout the life cycle of the component.

effect:

Get Dom operations, such as getting input focus

Get instances of subcomponents (only class components are available)

A global variable in a function component will not be declared repeatedly because of repeated render

Chestnuts

import {useRef} from 'react';


export default () => {
    const inputRef = useRef({value:0})
    return (
        <div>
            <h1>test</h1>
            <input type="text" ref={inputRef} />
            <button onClick={()=>{console.log(inputRef.current.value)}}>obtain input value</button>
            <button onClick={()=>{inputRef.current.focus()}}>obtain input focus</button>
        </div>
    )
}

useContext status data sharing

What does Context solve

In daily development, our parent-child components communicate through props. If we encounter cross level component communication, it is difficult for us to deal with it through props.

At this time, you can think about how to share the component state for use?

Context Redux .....

This section uses Context to share component data

What is Context

Data sharing, any component can access Context data.

In React, component data is transferred from top to bottom through prop. To realize global data transfer, you can use Context

be careful:

The main application scenario of Context is that many components at different levels need to access the same data. Use with caution, as this will make the reusability of components worse.

Create Context

Before using Context, you must create it. You can create a separate file for it to manage Context,

import React from 'react';

export const MyContext = React.createContext();

Use Context

When using Context, it is usually used on top-level components (parent components), and the internal components wrapped by it can enjoy the use and modification of state.

Through context Provider, and the value is passed through value = {}.

How do subcomponents use the value passed by Context?

You can easily get the corresponding value through usecontext () hook

// Context.js
import React from 'react';

export const MyContext = React.createContext();
import { useContext } from 'react';
import {MyContext} from '../Context/index'

const result = {
    code:200,
    title:'Data added successfully'
}
const Son = () => {
    const res = useContext(MyContext)
    return (
        <>
            <div>
                <h1>{res.code}</h1>
                <hr/>
                <h2>{res.title}</h2>
            </div>
        </>
    )
}


export default  () => {
    return (
        <MyContext.Provider value={result}>
            <div>
                <h1>Front end self-study community</h1>
                <Son/>
            </div>
        </MyContext.Provider>
    )
}

useMemo improves performance optimization

definition

useMemo is used for performance optimization to avoid high overhead calculation on each rendering by memorizing values.

useMemo parameter:

The return value of useMemo is the memoized value, which has the function of caching Array controls the array that useMemo re executes. useMemo will be re executed only when the state in array changes

be careful:

Do not pass the array, and each update will be recalculated Empty array, which will be calculated only once It depends on the corresponding value. When the corresponding value changes, it will be recalculated (it can depend on the value returned by another useMemo)

Chestnuts

import { useState, useMemo} from 'react';


export default () => {
    const  [count, setCount] = useState(0)
    const [num, setNum] = useState(0)
    const newValue = useMemo(()=>{
        console.log(`count Value is ${count}`)
        console.log(`num Value is ${num}`)
        return count+num
    },[count])
    return(
        <div>
            <h1>{count}</h1> 
            <button onClick={()=>{setCount(count+1)}}>count + 1</button>
            <hr/>
            <h1>{num}</h1> 
            <button onClick={()=>{setNum(num+1)}}>Num + 1</button>
            <hr/>
            <h2>{newValue}</h2>
        </div>
    )
}

Analytical chestnut

When you click five times to update the num value, the value of newValue in the page is always displayed as 0. Why?

Because I listened and recorded the value of count in useMemo. When the count value changes, the newValue on the page will be recalculated. Although you click Update num five times, the page has not been updated, but it has been cached. When you click update count, it will calculate the value of count+1 and the value cached in num, and the final result is 5.

The calculation consumption is reduced.

useCallback improves performance optimization

definition

useCallback can be said to be the syntax sugar of useMemo. If it can be implemented with useCallback, useMemo can be used. It is often used to optimize the performance of react.

Parameters of useCallback:

callback is a function used to process logic Array controls the array that useCallback re executes. When the array changes, useCallback will be re executed

use

It uses the same function as memuseback.

import { useState, useCallback} from 'react';


export default () => {
    const  [count, setCount] = useState(0)
    const [num, setNum] = useState(0)
    const newValue = useCallback(()=>{
        console.log(`count Value is ${count}`)
        console.log(`num Value is ${num}`)
        return count+num
    },[count])
    return(
        <div>
            <h1>{count}</h1> 
            <button onClick={()=>{setCount(count+1)}}>count + 1</button>
            <hr/>
            <h1>{num}</h1> 
            <button onClick={()=>{setNum(num+1)}}>Num + 1</button>
            <hr/>
            {/* The value returned by calling useCallback */}
            <h2>{newValue()}</h2>
        </div>
    )
}

Summary

The functions of useMemo and useCallback are similar. They are both optimized to improve performance.

Which way to best practice remains to be explored.

Readers are welcome to communicate with me.

What do you think of useMemo and useCallback on the Internet?

useCallback should indeed be used as a best practice if it is used in functional components, but its purpose is not only to cache the callback function with unchanged dependency (similar to useMemo), but also to ensure that the callback function is always the latest instance when the dependency changes, so as not to cause some unexpected problems, I feel that the latter is the starting point for using useCallback, not caching. Because you think, even if useCallback is not used, assuming that the callback function does not have any dependency state, can I directly declare this function outside the component? Isn't it freer for me to use ref directly? The name of useMemo itself is associated with the cache. In essence, it is to solve a problem. Do not directly create objects or methods in render, because each time the component is rendered, it will be created (such as style or some constant states), resulting in unnecessary waste of resources. Ideally, if there is a dependency, it should be recreated only when the dependency changes. If there is no dependency, it should be created only once. On the surface, if useMemo is used for all States, there must be no problem, but you still need to analyze this problem from the cost of caching. If the cost of using useMemo to cache a state is greater than its advantages, is it counterproductive?

If you have any comments on useMemo and useCallback, please comment below

useImperativeHandle

definition

useImperativeHandle allows you to customize the instance values exposed to the parent component when using ref. In most cases, you should avoid using imperative code such as ref. useImperativeHandle should be used with forwardRef.

useImperativeHandle function:

Child components can be exposed to parent component instances for use

Format: useimperativehandle (ref, () = > {}, [])

Parameter 1: instances exposed by child components to parent components

Parameter 2: function, passed parent component, operable instance and method

Parameter 3: listening status, update status

import {useState,useImperativeHandle, forwardRef,useRef} from 'react';


const Son = forwardRef( (props,ref) => {
    const inputRef = useRef(0)
    const domRef = useRef()
    const [state, setState] = useState('wait for')
    useImperativeHandle(ref,()=>({
        focus:() => {inputRef.current.focus()},
        domRef
    }))
    return (
        <div>
            <h1>{state}</h1>
            <hr/>
            <input type="text" ref={inputRef}/>
            <h2  ref={domRef}>test---------useImperativeHandle</h2>
        </div>
    )
})


export default () => {
    const refFather = useRef(0)
    return (
        <div>
            <h1>Parent component</h1>
            <Son ref={refFather} />
            <button onClick={()=>{refFather.current.focus()}}>Get sub component instance------obtain input focus</button>
            <button onClick={()=>{console.log(refFather.current.domRef.current.innerHTML)}}>Get sub component instance------obtain h2 Dom</button>
        </div>
    )
}

useReducer

definition

It is an alternative to useState. It receives a reducer in the form of (state, action) = > new state, and returns the current state and its matching dispatch method.

If you are familiar with the use of Redux, you will be familiar with using useReducer and start the train.

Implement an adder and subtractor using Reducer

import {useReducer} from 'react';


export default () => {
    const [state, dispatch] = useReducer((state,action)=> {
        switch (action.type){
            case 'addNum':
                return {
                    num:state.num+1
                }
            case 'subtractNum':
                return {
                    num:state.num-1
                }
        }
            
    },{
        num:0
    })
    return (
        <div>
            <h2>{state.num}</h2>
            <button onClick={()=>{dispatch({type:'addNum'})}}> increase num</button>
            <button onClick={()=>{dispatch({type:'subtractNum'})}}> reduce num</button>
        </div>
    )
}

Added by The_Stranger on Tue, 15 Feb 2022 05:57:33 +0200