npx

  • Avoid installing global modules
  • Invoke modules installed inside the project

NPM run creates a new shell and adds node_modules to the system environment variable, which is then deleted

Why React Hook

  • Components have difficulty reusing state logic
  • Complex components are difficult to understand, especially life cycle functions
  • The React component has always been a function and uses hooks to fully embrace functions

useState

  • Triggers the render of the component
import React, {useState} from 'react'

const LikeButton: React.FC = () = > {
    const [like, setLike] = useState(0)
    const [on, setOn] = useState(true)
    return (
        <>
        <button onClick={()= >{setLike(like + 1)}}> {like} like</button>
        <button onClick={()= >{setOn(! on)}}> {on ? 'on' : 'off'}</button>
        </>)}export default LikeButton;
Copy the code

useEffect

Effect that does not need to be cleaned

UseEffect to complete title updates using DOm

    // This is executed by default after the first render and after every update
    useEffect(() = > {
        document.title = ` clicked${like}Time `
    })
Copy the code

Effects that need to be cleared

Use useEffect to complete a mouse tracker

import React, {useState, useEffect} from 'react'

const MouseTracker: React.FC = () = > {
    const [positions, setPositions] = useState({x: 0.y: 0})
    useEffect(() = > {
        console.log('add effect', positions.x)
        const mouseTracker = (e: MouseEvent) = > {
            console.log('inner')
            setPositions({x: e.x, y: e.y})
        }
        document.addEventListener('click', mouseTracker)
        return () = > {
            console.log('remove effect', positions.x)
            document.removeEventListener('click', mouseTracker)
        }
    })
    console.log('before render', positions.x)
    return (
        <p>X: {positions.x}, Y: {positions.y}</p>)}export default MouseTracker
Copy the code

Add effect is always executed after before Render

Control the useEffect execution

 useEffect(() = > {
        console.log('add effect', positions.x)
        const mouseTracker = (e: MouseEvent) = > {
            console.log('inner')
            setPositions({x: e.x, y: e.y})
        }
        document.addEventListener('click', mouseTracker)
        return () = > {
            console.log('remove effect', positions.x)
            document.removeEventListener('click', mouseTracker)
        }
    }, [])
Copy the code

So this is actually componentDidMount and componentWillUnmount

Customize the Hook

  • Extract component logic into reusable functions
  • Code: Use custom Hook abstract mouse tracker
import React, {useState, useEffect} from 'react'

const useMousePosition = () = > {
    const [positions, setPositions] = useState({x: 0.y: 0})
    useEffect(() = > {
        console.log('add effect', positions.x)
        const mouseTracker = (e: MouseEvent) = > {
            console.log('inner')
            setPositions({x: e.x, y: e.y})
        }
        document.addEventListener('mousemove', mouseTracker)
        return () = > {
            console.log('remove effect', positions.x)
            document.removeEventListener('mousemove', mouseTracker)
        }
    }, [])
    return positions;
}
export default useMousePosition
Copy the code

HOC high-level components

  • A higher-order component is a function that takes a component as an argument and returns a new component
  • Common implementation methods: property proxy and reverse inheritance
  • Disadvantage:
    • Add unnecessary interface structure instead of pure logic
    • It is difficult to understand
    • To understand, you also need to look for the wrapped component

Use custom hook to complete useURLLoader

import {useState, useEffect} from 'react'
import axios from "axios";

const useURLLoader = (url: string, deps: any[] = []) = > {
    const [data, setData] = useState<any> (null);
    const [loading, setLoading] = useState(false)
    useEffect(() = > {
        setLoading(true)
        axios.get(url).then(res= > {
            setData(res.data)
            setLoading(false)
        })
    },deps)
    return [data, loading]
}

export default useURLLoader;
Copy the code

useRef

To solve what problem

  • The state value in any render is constant and does not change over time. The render output changes because the component is called time after time and the state value in the component render is independent of the other renders.
  • The props and state values are always the same in any render, and if the props and state values are independent of each other in any render, then any values used for them are independent of each other.

role

  • The link between multiple renders
    1. UseRef keeps unique references in all render
    2. Note that ref changes are not rerender
import React, {useState, useEffect, useRef} from 'react'

const LikeButton: React.FC = () = > {
    const [like, setLike] = useState(0)
    // {current: 0}
    const likeRef = useRef(0)
    // This is executed by default after the first render and after every update
    useEffect(() = > {
        document.title = ` clicked${like}Time `
    })
    function handleAlertClick(){
        setTimeout(() = > {
            alert(` clicked${likeRef.current}Time `)},3000)}return (
        <>
            <button onClick={()= >{ setLike(like + 1) likeRef.current++; }} > {like} to assist</button>
            <button onClick={handleAlertClick}>Alert!</button>
        </>)}export default LikeButton;
Copy the code
  • Simulate the componentDidUpdate life cycle
import React, {useState, useEffect, useRef} from 'react'

const LikeButton: React.FC = () = > {
 		const didMountRef = useRef(false)
    / / simulation componentDidUpdate
    useEffect(() = > {
        if (didMountRef.current) {
            console.log('this is updated')}else {
            didMountRef.current = true; }})return (
        <>
    
        </>)}export default LikeButton;   

Copy the code
  • Accessing dom nodes
import React, {useState, useEffect, useRef} from 'react'

const LikeButton: React.FC = () = > {
    const domRef = useRef<HTMLInputElement>(null)
    / / the input focus
    useEffect(() = > {
        if(domRef && domRef.current){
            domRef.current.focus()
        }
    })
  
    return (
        <>
            <input type="text" ref={domRef}/>
        </>)}export default LikeButton;
Copy the code

useContext

  • Address multiple layers of transitive properties

Rules of the Hook

  • Use hooks only at the top level
  • Only the React function calls the hook

Other hook

  • UseReducer: Simplifies useState with complex logic
  • useCallback