useState

Using a state

const [n,setN] = React.useState(0)
const [user,setUser] = React.useState({name:'Jack'})
Copy the code

Matters needing attention

  • Nonlocal update

    If state is an object, setState does not automatically merge properties

    import React, { useState } from "react";
    import "./styles.css";
    
    export default function App() {
      const [user,setUser] = useState({name:'Jack',age:18})
      const Click = ()=>{
        setUser({
          name:'Tom'})}return (
        <div className="App">
          <h1>{user.name}</h1>
          <h2>{user.age}</h2>
          <button onClick={Click}>Click</button>
        </div>
      );
    }
    Copy the code

    The effect

    You can use… Operator resolution

  • Address to change

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

    import React, { useState } from "react";
    import "./styles.css";
    
    export default function App() {
      const [user,setUser] = useState({name:'Jack',age:18})
      const Click = ()=>{
      	console.log('Clicked')
      	user.name = 'Tom'
        setUser(user)
      }
      return (
        <div className="App">
          <h1>{user.name}</h1>
          <h2>{user.age}</h2>
          <button onClick={Click}>Click</button>
        </div>
      );
    }
    Copy the code

    The effect

  • UseState receiver function

    This function returns the initial state and is executed only once to reduce unnecessary computation

    const [user,setUser] = useState(()=>({name:'Jack',age:9+9}))
    Copy the code
  • SetN accept function

    When we execute the following code, the result is not 2 as we expected, but 1

    import React, { useState } from "react";
    
    export default function App() {
      const [n,setN] = useState(0)
      const Click = ()=>{
      	setN(n+1)
        setN(n+1)
      }
      return (
        <div className="App">
          <h1>{n}</h1>
          <button onClick={Click}>+1</button>
        </div>
      );
    }
    Copy the code

    The effect

    Using setN accept function can solve the above problems

    const Click = ()=>{
      	setN(i => i+1)
        setN(x => x+1)
      }
    Copy the code

    The effect

useReducer

UseReducer is used to practice the Flux/Redux idea

  1. Create an initial valueinitialState
  2. Create all operationsreducer(state,action)
  3. To pass touseReducerGet read and writeAPI
  4. callWrite ({type:' operation type '})
import React, { useReducer } from "react";
import "./styles.css";
const initial = {
  n:0
}
const reducer=(state,action)=>{
  if(action.type==='add') {return {n:state.n+action.number}
  }else if(action.type==='sub') {return {n:state.n-action.number}
  }else{
    throw new Error("unkown type")
  }
}
export default function App() {
  const [state,dispatch]=useReducer(reducer,initial)
  const {n}=state
  const Click = ()=>{
    dispatch({type:'add',number:2})
  }
  const Click2 = ()=>{
    dispatch({type:'sub',number:1})}return (
    <div className="App">
      <h1>{n}</h1>
      <button onClick={Click}>+2</button>
      <button onClick={Click2}>-1</button>
    </div>
  );
}

Copy the code

The effect

In general, useReducer is a complex version of useState. Note that useReducer also does not automatically merge properties

useContext

UseContext is a local global variable

  1. useC =createContext(initial)Create context
  2. use<C.provider>Delineate the scope of the context
  3. Within scope, useuseContext(C)To use context
import React, { createContext, useState, useContext } from "react";
import "./styles.css";

const C = createContext(null)
export default function App() { 
  const [n,setN] = useState(0)
  return (
    <C.Provider value={{n,setN}}>
      <div className="App">
        <Father/>
      </div>
    </C.Provider>
  );
}

function Father(){
  return(
    <div>
      Father
      <Son />
    </div>
  )
}
function Son(){
  const {n,setN} = useContext(C)
  const Click=()=>{
    setN(n+1)}return(
    <div>
      <p>Son n:{n}</p>
      <button onClick={Click}>+1</button>
    </div>
  )
}
Copy the code

The effect

Note: useContext is not responsive. If another module changes the value of C, the other module will not notice the change. When the property is changed, the App will be notified to re-render

useEffect

Function components do not have the lifecycle found in class components, hence the useEffect API, which simulates the lifecycle

To simulate the constructor

When executed, the function component is equivalent to constructorCopy the code

Simulation shouldComponentUpdate

Use React. Memo and useMome to solve this problemCopy the code

To simulate the render

The return value of the function component is the return value of renderCopy the code

Simulation componentDidMount

UseEffect (()=>{console.log(' first render ')},[])Copy the code

Simulation componentDidUpdate

UseEffect (() = > {the console. The log (' arbitrary properties changed ')}) useEffect (() = > {the console. The log (' attribute n changed ')}, [n])Copy the code

Simulation componentWillUnmount

UseEffect (() = > {the console. The log (' first rendering) return () = > {the console. The log (' components to destroyed ')}})Copy the code

Multiple Useeffects can occur and are executed in the order in which they occur

useLayoutEffect

UseLayoutEffect is executed before the browser renders

Features:

  • useLayoutEffectIs always better thanuseEffectTo perform first
  • useLayoutEffectBest to influenceLayout

useMemo

Switch to use React useMemo

useRef

Binding the DOM

import React, { useRef, useEffect } from "react";
import "./styles.css";

export default function App() {
  const myRef = useRef(null)
  useEffect(()=>{
    myRef.current.value='Input field'}, [])return (
    <div className="App">
     <input type="text" ref={myRef} />
    </div>
  );
}
Copy the code

The effect

The parent component calls the child component method

import React, { useState, useRef, useImperativeHandle } from "react";
import "./styles.css";

export default function App() {
  const myRef = useRef()
  const Click =()=>{
    myRef.current.add()
  }
  return (
    <div className="App">
     <div>Father</div>
     <button onClick={Click}>+1</button>
     <Son ref={myRef}/>
    </div>
  );
}
const Son = React.forwardRef((props,ref)=>{
  const [n,setN]=useState(0)
  useImperativeHandle(ref,()=>({
    add:()=>{
      setN(i=>i+1)}}))return(
    <div>
      <div>Son: {n}</div>
    </div>
  )
})
Copy the code

The effect

Note:

  • Due to the function componentpropsDoes not containref, need to useReact.forwardRef, as
  • useImperativeHandleYou can customizeref

Store previous values

import React, { useState, useEffect, useRef } from "react";
import "./styles.css";


export default function App() {
  console.log('App executed ')
  const [n,setN]=useState(0)
  const count = useRef(0)
  const Click =()=>{
    setN(i=>i+1)
  }
  useEffect(()=>{
    count.current+=1
    console.log(count.current)
  })
  return (
    <div className="App">
     <div>{n}</div>
     <button onClick={Click}>+1</button>
    </div>
  );
}
Copy the code

The effect