1 useState

  • Using a state

    const [n, setN] = React.useState(0)
    const [user,setUser] = React.useState({name:'frank'})
    Copy the code
  • Note 1: Cannot be partially updated

    If it’s an object, we can’t partially setState, because setState will help us merge properties

    import React, {useState} from "react"
    import ReactDom from "react-dom"
    
    function App() {
        const [user, setUser] = useState({name: 'f'.age: 18})
        const onClick = () = >{ setUser({ ... user,// Copy all attributes of user
                name: 'jack'// Override the previous name with name: 'jack'})}return (
            <div className="App">
                <h1>{user.name}</h1>
                <h2>{user.age}</h2>
                <button onClick={onClick}>Click</button>
            </div>)}const rootElement = document.getElementById("root")
    ReactDom.render(<App />, rootElement)
    Copy the code
  • Note: Change the address

    SetState (obj) If the obj address does not change, React assumes that the data has not changed

    const onClick = () = > {
            setUser({
            user.name = 'jack'
            setUser(user)
      			// The user address does not change, the UI will not update
        }
    Copy the code
  • UseState receiver function

    The benefit is to reduce the amount of extra computation (use less)

    const [user, setUser] = useState(() = > ({name: 'frank'.age: 18}))
    Copy the code
  • SetState accepts the function

    import React, {useState} from "react"
    import ReactDom from "react-dom"
    
    function App() {
        const [n,setN] = useState(0)
        const onClick = () = > {
            // setN(n + 1)
            // setN(n + 1)
            SetN doesn't change the value of n directly. It's a function
    
            setN(i= > i +1)
            setN(i= > i +1)}return (
            <div className="App">
                <h1>n : {n}</h1>
                <button onClick={onClick}>+ 2</button>
            </div>)}const rootElement = document.getElementById("root")
    ReactDom.render(<App/>, rootElement)
    Copy the code

2 useReducer

  • To practice the ideas of Flux/Redux

    Four steps

    • Create the initial value initialState
    • Create all operations Reducer (state, action)
    • Pass to useReducer to get read and write apis
    • Call write ({type: ‘operation type ‘})
  • example

    import React, {useReducer} from "react"
    import ReactDom from "react-dom"
    
    const initialState = {
        n: 0
    }
    const reducer = (state, action) = > { // (old state, type of operation)
        if (action.type === 'add') {
            return {n: state.n + action.number}
        } else if (action.type === 'multi') {
            return {n: state.n * 2}}else {
            throw new Error('unknown type')}}function App() {
        const [state, dispatch] = useReducer(reducer, initialState)
        const {n} = state
        // Get a read API state and a write API dispatch
    
        const onClick = () = > {
            dispatch({type: 'add'.number: 1})}const onClick2 = () = > {
            dispatch({type: 'add'.number: 2})}return (
            <div className="App">
                <h1>n : {n}</h1>
                <button onClick={onClick}>+ 1</button>
                <button onClick={onClick2}>+ 2</button>
            </div>)}const rootElement = document.getElementById("root")
    ReactDom.render(<App/>, rootElement)
    Copy the code

3 useContext

  • Context (all the other variables you need to know to run a program)

    • A global variable is a global context
    • Context is a local global variable
  • Method of use

    • Create the context using C = createContext(initial)
    • Use

      to define the scope
    • Use useContext(C) in scope to useContext
  • example

    import React, {useState, createContext, useContext} from "react"
    import ReactDom from "react-dom"
    
    / / 1.
    const C = createContext(null)
    
    function App() {
        const [n, setN] = useState(0)
        return (
            // 2. Use < c. provider> to delimit the value read and write interfaces of scope value
            // n and setN can be shared with any component of the children
            <C.Provider value={{n, setN}} >
                <div className="App">
                    <Farther/>
                </div>
            </C.Provider>)}function Farther() {
        return (
            <div>I am a father<Child/></div>)}function Child() {
        const {n, setN} = useContext(C)
        const onClick = () = > {
            setN(i= > i + 1)}return (
            <div>I'm the son, and I get n: {n}<button onClick={onClick}>+ 1</button>
            </div>)}const rootElement = document.getElementById("root")
    ReactDom.render(<App/>, rootElement)
    Copy the code
  • Matters needing attention

    It’s not reactive, you change the value of C in one module, and the other module doesn’t notice the change

4 useEffect

  • Side effects that change the environment are side effects, such as modifying document.title, but we don’t have to put side effects in useEffect, it’s actually better to call afterRender, the function that is called after each render

  • use

    • Used as componentDidMount, [] as the second argument

    • Used as componentDidUpdate to specify dependencies

    • Used as componentWillUnmount, via return

      The above three uses can exist simultaneously

  • The characteristics of

    If multiple USEeffects exist at the same time, they are executed in the order in which they occur

  • example

    import React, {useState, useEffect} from "react"
    import ReactDom from "react-dom"
    
    function App() {
        const [n, setN] = useState(0)
        const onClick = () = > {
            setN(i= > i + 1)
        }
    
        useEffect(() = > {
            console.log('Execute this sentence after the first render')}, [])// If the variable changes, it will not be executed again
    
        useEffect(() = > {
            console.log('Execute this sentence after each render')})// Execute when any variable changes
    
        useEffect(() = > {
            if(n ! = =0) {
                console.log('n 'changes.)
            }
        }, [n]) // Execute when n changes
        return (
            <div>
                n : {n}
                <button onClick={onClick}>+ 1</button>
            </div>)}const rootElement = document.getElementById("root")
    ReactDom.render(<App/>, rootElement)
    Copy the code

5 useLayoutEffect

  • Layout side effect

    • UseEffect is executed after the browser rendering is complete
    • UseLayoutEffect is executed before the browser renders
  • The characteristics of

    • UseLayoutEffect is always executed before useEffect
    • Tasks in useLayoutEffect best affect Layout
  • experience

    UseEffect is preferred for user experience

6 useMemo

  • Example: redundant render

    import React from "react";
    import ReactDOM from "react-dom";
    
    function App() {
        const [n, setN] = React.useState(0);
        const [m, setM] = React.useState(0);
        const onClick = () = > {
            setN(n + 1);
        };
    
        return (
            <div className="App">
                <div>
                    <button onClick={onClick}>update n {n}</button>
                </div>
                <Child data={m}/>{/ *<Child2 data={m}/>* /}</div>
        );
    }
    
    function Child(props) {
        console.log("Child executed");
        console.log(Let's say I have a lot of code here.)
        return <div>child: {props.data}</div>;
    }
    
    const Child2 = React.memo(Child);
    
    const rootElement = document.getElementById("root");
    ReactDOM.render(<App />, rootElement);
    Copy the code

    Effect: Click the button to update n, and the code in the child component executes

  • Rewrite the above example using memo

    const Child = React.memo(props= > {
        console.log("Child executed");
        console.log(Let's say I have a lot of code here.)
        return <div>child: {props.data}</div>;
    })
    Copy the code
  • However, there is a bug in the react.memo function. After adding the listener function, although the function is the same as the old function, the address is different. The function will generate the new address after the component is re-rendered

    import React from "react";
    import ReactDOM from "react-dom";
    
    function App() {
        const [n, setN] = React.useState(0);
        const [m, setM] = React.useState(0);
        const onClick = () = > {
            setN(n + 1);
        };
        const onClickChild = () = > {} // Because APP() is re-executed, this sentence is re-executed, the address of the function is changed
    
        return (
            <div className="App">
                <div>
                    <button onClick={onClick}>update n {n}</button>
                </div>
                <Child data={m} onClick={onClickChild}/>
            </div>
        );
    }
    
    const Child = React.memo(props= > {
        console.log("Child executed");
        console.log(Let's say I have a lot of code here.)
        return <div onClick={props.onClick}>child: {props.data}</div>;
    })
    
    const rootElement = document.getElementById("root");
    ReactDOM.render(<App/>, rootElement);
    Copy the code
  • UseMemo rewrite can be solved

    const onClickChild = useMemo(() = > {
            return () = > {
            }
        }, [m])
    Copy the code
  • The characteristics of

    • The first parameter is theta()=> valueThe second parameter is dependency[n,m]
    • A new value is computed only if the dependency changes, and if the dependency does not change, the previous value is reused
  • Pay attention to

    If your value is a function, then you have to write

    useMemo(() = > (x) = > console.log(x))
    Copy the code

    This is a function that returns a function, which is hard to use, hence useCallBack

  • useCallBack

    The usage useCallback(x => log(x), [m]) is equivalent to

    useMemo(() => x => log(x), [m])

7 useRef

  • purpose

    If a value is required, it remains the same as the component is rendered

  • use

    • Initialization: const count = useRef(0)

    • Read: count. The current

      Why current? To ensure that useRef is the same value both times (only references can do this)

  • forwardRef

    Because the PROPS does not contain ref, the forwardRef is required