Study notes from three latitudes:

  1. Why 🤔 ️
  2. How to use 🔨
  3. Knowledge ⛽ ️

useState

Why use useState?

UseState comes in the form of using class setState in function components, stimulating!

The problem is that when a function component wants to maintain its own state, it has to convert to class. This is troublesome!

How do I use useState?

const [name, setName] = useState('rose')
Copy the code

useState

😄1. Key: The initial value of useState is valid only for the first time

I didn’t take it seriously until I hit a hole…

🌰2. For example:

When I click the button to change the value of name, I find that in the Child component, it is received, but the value is not assigned to name through useState!

Conclusion: Practice test knowledge point! 😭

const Child = memo(({data}) =>{
    console.log('child render... ', data)
    const [name, setName] = useState(data)
    return (
        <div>
            <div>child</div>
            <div>{name} --- {data}</div>
        </div>
    );
})

const Hook =()=>{
    console.log('Hook render... ')
    const [count, setCount] = useState(0)
    const [name, setName] = useState('rose')

    return(
        <div>
            <div>
                {count}
            </div>
            <button onClick={()=>setCount(count+1)}>update count </button>
            <button onClick={()=>setName('jack')}>update name </button>
            <Child data={name}/>
        </div>
    )
}
Copy the code

useEffect

Why useEffect?

UseEffect is the use of a class lifecycle function in a function component, or a combination of all functions. Exciting!

How do I use useEffect?

useEffect(()=>{
    ...
})
Copy the code

useEffect

😄1. First time only componentDidMount, can be used to request asynchronous data… ,

UseEffect Finally, the addition of [] indicates only the first execution

UseEffect (()=>{const users = get user info ()},[])Copy the code

😄2. Instead of life functions such as willUpdate that are executed every time you render

UseEffect Finally, without [], every render is executed

UseEffect (()=>{const users = get user info every time ()})Copy the code

😄3. It takes a bit of money to perform every rendering, so:

UseEffect finally, add [], and the field in [] indicates that the field has changed before this effect is executed

UseEffect (() => {const users = (name)},[name])Copy the code

😄4. What if I want to separate name and age:

Multiple useeffects can be written

},[name]) useEffect(() => {const users = (const users =)},[name]) useEffect(() => {const users = },[age]Copy the code

😄5. How to use useEffect if we want to unsubscribe from a subscription during the willUnMount lifecycle:

You can unsubscribe from an effect return

UseEffect (() => {const subscription =return() => {cancel the subscription to the national people eat information! }}, [])Copy the code

Why unsubscribe?

UseEffect is used after render. If useEffect has a setInterval… Every time render is rendered, useEffect creates another setInterval, and chaos ensued… You can delete the following example return and feel it

useEffect(() => {
        console.log('use effect... ',count)
        const timer = setInterval(() => setCount(count +1), 1000)
        return ()=> clearInterval(timer)
    })
Copy the code

😄6. UseEffect some rules for dark stamping:

1. The value of state used in useEffect is fixed in useEffect and will not be changed unless useEffect is refreshed

 const [count, setCount] = useState(0)
    useEffect(() => {
        console.log('use effect... ',count)
        const timer = setInterval(() => {
            console.log('timer... count:', count)
            setCount(count + 1)
        }, 1000)
        return ()=> clearInterval(timer)
    },[])
    
Copy the code

2. UseEffect cannot be detected

const [count, setCount] = useState(0)
if(2 < 5){
   useEffect(() => {
        console.log('use effect... ',count)
        const timer = setInterval(() => setCount(count +1), 1000)
        return ()=> clearInterval(timer)
    }) 
}
Copy the code

3. UseEffect cannot be interrupted

const [count, setCount] = useState(0)
useEffect(...)

returnUseEffect (...) }Copy the code

The specific reason has to do with the useEffect generation execution rule: read the documentation!

useRef

Why use useRef?

As mentioned earlier:

The value of state used in useEffect is fixed in useEffect and will not be changed unless useEffect refreshes and resets the value of state

 const [count, setCount] = useState(0)
    useEffect(() => {
        console.log('use effect... ',count)
        const timer = setInterval(() => {
            console.log('timer... count:', count)
            setCount(count + 1)
        }, 1000)
        return ()=> clearInterval(timer)
    },[])
    
Copy the code

The useEffect state value is fixed, and the solution is to use the useRef function:

The global scope is modified in one place and updated everywhere else.

How to use useRef?

const countRef = useRef(0)

Copy the code

UseRef Knowledge points collection

😄 1. This is equivalent to the global scope, which is modified in one place and updated everywhere else…

 const [count, setCount] = useState(0)
 const countRef = useRef(0)
useEffect(() => {
    console.log('use effect... ',count)
    const timer = setInterval(() => {
        console.log('timer... count:', countRef.current)
        setCount(++countRef.current)
    }, 1000)
    return ()=> clearInterval(timer)
},[])
Copy the code

😄 2. Universal operation, used to manipulate the DOM

const btnRef = useRef(null)

click me

Remember to unbind events! return ()=> btnRef.current.removeEventListener(‘click’,onClick, false)

const Hook =()=>{
    const [count, setCount] = useState(0)
    const btnRef = useRef(null)

    useEffect(() => {
        console.log('use effect... ')
        const onClick = ()=>{
            setCount(count+1)
        }
        btnRef.current.addEventListener('click',onClick, false)
        return ()=> btnRef.current.removeEventListener('click',onClick, false)
    },[count])

    return(
        <div>
            <div>
                {count}
            </div>
            <button ref={btnRef}>click me </button>
        </div>
    )
}
Copy the code

useMemo

Why use useMemo?

An 🌰 :

const Child = memo(({data}) =>{
    console.log('child render... ', data.name)
    return (
        <div>
            <div>child</div>
            <div>{data.name}</div>
        </div>
    );
})

const Hook =()=>{
    console.log('Hook render... ')
    const [count, setCount] = useState(0)
    const [name, setName] = useState('rose')

    const data = {
        name
    }

    return(
        <div>
            <div>
                {count}
            </div>
            <button onClick={()=>setCount(count+1)}>update count </button>
            <Child data={data}/>
        </div>
    )
}
Copy the code

When we click on the button to update count, the Effect component will render, and once render, this line of code will be executed:

   const data = {
        name
    }
Copy the code

This line of code will generate an object with a new memory address, and then the memo’s Child component will be rerender, even though the value used by the Child will not change!

So redundant render, sensory performance wasted! So here comes useMemo as a transient capability.

How do I use useMemo?

  const data = useMemo(()=>{
        return {
            name
        }
    },[name])
Copy the code

[name], useMemo, as a temporary storage, temporarily stores the last name result.

When we compare the last name, we find the name value has not changed! Data will not be reassigned to a new object this time!

Without a new object, there is no new memory address, and the Child will not be rerendered!

const Child = memo(({data}) =>{
    console.log('child render... ', data.name)
    return (
        <div>
            <div>child</div>
            <div>{data.name}</div>
        </div>
    );
})

const Hook =()=>{
    console.log('Hook render... ')
    const [count, setCount] = useState(0)
    const [name, setName] = useState('rose')

   const data = useMemo(()=>{
        return {
            name
        }
    },[name])
    
    return(
        <div>
            <div>
                {count}
            </div>
            <button onClick={()=>setCount(count+1)}>update count </button>
            <Child data={data}/>
        </div>
    )
}
Copy the code

UseMemo Knowledge points collection

UseMemo has always had a memo.

😄 1. First, the memo is used as a PureComponent of a function component

However, if the function component is wrapped in react. Memo and its implementation has a Hook for useState or useContext, it will still re-render when the context changes.

😄 2. Also, the memo is shallow comparison, the object only compare memory address, as long as the memory address does not change, even if the value in your object changes will not trigger render

😄 3. Finally, what useMemo does, and here comes useMemo as a temporary storage capability:

useCallback

Why use useCallback?

UseMemo solves the problem of caching values, but what about functions?

When you click on the count button, the Effect component render is rendered:

   const onChange=(e)=>{
        setText(e.target.value)
   }
    
Copy the code

The onChange function is regenerated and assigned to the Child component. The shallow comparison fails and the Child component successfully rerenders, even though the Child component did nothing!

const Child = memo(({data, onChange}) =>{
    console.log('child render... ')
    return (
        <div>
            <div>child</div>
            <div>{data}</div>
            <input type="text" onChange={onChange}/>
        </div>
    );
})

const Hook =()=>{
    console.log('Hook render... ')
    const [count, setCount] = useState(0)
    const [name, setName] = useState('rose')
    const [text, setText] = useState(' ')

   const onChange=(e)=>{
        setText(e.target.value)
   }
    
    return(
        <div>
            <div>count: {count}</div>
            <div>text : {text}</div>
            <button onClick={()=>setCount(count + 1)}>count + 1</button>
            <Child data={name} onChange={onChange}/>
        </div>
    )
}

Copy the code

How do I use useCallback?

   const onChange = useCallback((e)=>{
        setText(e.target.value)
   },[])
Copy the code

UseCallback knowledge point collection

😄1. UseMemo is similar to useCallback in that it serves as a cache. The essential difference may be:

UseMemo caches values

UseCallback is the cache function

😄2. No dependencies, add empty dependencies, that is, empty arrays!

useReducer

Why use useReducer?

As the name implies, the useReducer is the reducer in the class

How to use useReducer?

An 🌰 :

const reducer =(state = 0, {type})=>{
    switch (type) {
        case "add":
            return state+1
        case 'delete':
            return state-1
        default:
            return state;
    }
}

const Hook =()=>{
    const [count, dispatch] = useReducer(reducer, 0)
    return(
        <div>
           count:{count}
           <button onClick={()=> dispatch({type:'add'})}>add</button>
            <button onClick={()=> dispatch({type:'delete'})}>delete</button>
        </div>
    )
}

export default Hook
Copy the code

A collection of useReducer knowledge points

No special… 😼

useContext

Why use useContext?

UseContext is the context in the class.

How do I use useContext?

import React, {useContext, useReducer} from 'react'

const reducer = (state = 0, {type}) => {
    switch (type) {
        case "add":
            return state + 1
        case 'delete':
            return state - 1
        default:
            return state;
    }
}
const Context = React.createContext(null);

const Child = () => {
    const [count, dispatch] = useContext(Context)
    return( <div> <div>child... {count}</div> <button onClick={() => dispatch({type: 'add'})}>child add</button>
            <button onClick={() => dispatch({type: 'delete'})}>child delete</button>
        </div>

    )
}

const Hook = () => {
    const [count, dispatch] = useReducer(reducer, 10)
    return (
        <Context.Provider value={[count, dispatch]}>
            <div>
                <div>mom ... {count}</div>
                <Child/>
                <button onClick={() => dispatch({type: 'add'})}>mom add</button>
                <button onClick={() => dispatch({type: 'delete'})}>mom delete</button>
            </div>
        </Context.Provider>
    )
}

export default Hook

Copy the code

UseContext iS a collection of knowledge points

No special… 😼

Custom hook!

Define a custom hook that listens for window width and height when resize

import {useEffect, useState} from "react";

export const useWindowSize = () => {
    const [width, setWidth] = useState()
    const [height, setHeight] = useState()

    useEffect(() => {
        const {clientWidth, clientHeight} = document.documentElement
        setWidth(clientWidth)
        setHeight(clientHeight)
    }, [])

    useEffect(() => {
        const handleWindowSize = () =>{
            const {clientWidth, clientHeight} = document.documentElement
            setWidth(clientWidth)
            setHeight(clientHeight)
        };

        window.addEventListener('resize', handleWindowSize, false)

        return () => {
            window.removeEventListener('resize',handleWindowSize, false)}})return [width, height]
}

Copy the code

How to use:

const [width, height] = useWindowSize()
Copy the code

The last