useState

  • Using useState allows functional components to have state as well.
  • Grammar:const [xxx, setXxx] = React.useState(initValue) initValueIs the initial value
  • Return value: an array of two elements, the first being the internal current state value, and the second being the function to update the state value
  • SetXxx ()
// 1. setXxx(newValue): specifies the new state value directly, and internally overwrites the original state value
const [count,setCount] = React.useState(0)
function add(){
    setCount(count+1)}Copy the code
// 2. The argument is a function that receives the original status value and returns the new status value, internally overwriting the original status value
const [count,setCount] = React.useState(0)
function add(){
    setCount(value= >value+1)}Copy the code

useEffect

  • UseEffect enables functional components to perform life-cycle functions
Syntax and Description: useEffect(() = > { 
          // You can do anything with side effects here
          return () = > { // Execute before component uninstallation
            // equivalent to componentWillUnmount
          }
        }, [stateValue]) 
        // If [] is specified, the callback will only be executed after the first render()
        // If not, the mount and each update will be performed
Copy the code
  • UseEffect The return of the first argument is followed by a function that is equivalent tocomponentWillUnmount
  • UseEffect if the second parameter is left blank, then each render will be executed, equivalent tocomponentDidUpdate
  • UseEffect if the second argument is an empty arraycomponentDidMount
  • UseEffect The second argument can be used to specify that a property has changed before it is executed
const [count, setcount] =  React.useState(0)
const [name, setname] =  React.useState('zxx')
React.useEffect(() = >{
	console.log('Count changes, name changes not executed')
},[count])
Copy the code

useLayoutEffect

  • Usage anduseEffectSame, but with a slightly different effect
  • useEffectExecutes after the rendered content is updated to the DOM and does not block DOM updates
  • useLayoutEffectExecutes until rendered content is updated to the DOM, blocking DOM updates
  • useLayoutEffectThe execution of theuseEffect, so if you want to modify component element styles, useuseLayoutEffect

useContext

  • useContextThis allows us to share variables directly across the component hierarchy
  • First in the parent component
// You want to pass two data through context
import React ,{useContext}from 'react'
const CountContext = React.createContext()  
const NameContext = React.createContext()  
export default function Father() {
  
  return (
    <div>
      <CountContext.Provider value={15}>
        <NameContext.Provider value={'sss'} >
        <Son/>
        </NameContext.Provider>
      </CountContext.Provider>
    </div>)}Copy the code
  • Accepted in descendant components
function Son(){
   // The useContext argument must be the context object itself, if not imported itself
  const countInfo = useContext(CountContext)
  const nameInfo = useContext(NameContext)
  return (
    <div>
      <h2>The Header component</h2>
      <p>{countInfo}</p>
      <p>{nameInfo}</p>
    </div>)}Copy the code

useReducer

UseReducer is just an alternative to useState. If the state processing logic is complicated, we can use useReducer to split it

  • Const [state,dispatch] = useReducer(reducer)
import React ,{useReducer}from 'react'
Create reducer, accept state and action
function reducer(state,action){
  switch (action.type) {
    case 'increment':
      return{... state,num:state.num+1}
    case 'decrement':
      return{... state,num:state.num-1}
    default:
      throw new Error();
  }
}
function Home(){
  / / use useReducer
  const [state,dispatch] = useReducer(reducer,{num:0})
  return (
    <div>
      <h2>The Header data: {state. The num}</h2>Distributing the action * /} {/ *<button onClick={()= >dispatch({type:'decrement'})}>-1</button>
      <button onClick={()= >dispatch({type:'increment'})}>+1</button>
    </div>)}function About(){
  const [state,dispatch] = useReducer(reducer,{num:25})
  return(
    <>
      <h2>The About data: {state. The num}</h2>
      <button onClick={()= >dispatch({type:'decrement'})}>-1</button>
      <button onClick={()= >dispatch({type:'increment'})}>+1</button>
    </>)}export default function App() {
  return (
    <div>
      <Home></Home>
      <About></About>
    </div>)}Copy the code

useCallback

The actual purpose of useCallback is to optimize performance

  • useCallbackReturns the memoized value of a function
  • In the case of invariant dependencies, the same value is returned multiple times when the definition is repeated

Use with memo: When the memo is not used, the parent component is re-rendered and the children must be re-rendered, so using the Memo prevents this from happening

import React,{useState,memo,useCallback} from 'react'
// When useCallback is not used, all components are re-rendered every time they are added or subtracted
function Home(props){
  console.log("HOME rendered");
  return(
    <div>
      <p>Home</p>
      <button onClick={()= >Props. Handle ()} ></button>
    </div>)}function About(props){
  console.log("ABOUT rendered");
  return(
    <div>
      <p>About</p>
      <button onClick={()= >Props. Handle ()} ></button>
    </div>)}const MemoHome = memo(Home)
const MemoAbout = memo(About)
export default function App() {
  console.log("APP rendered");
  const [numState,setNum] = useState(12)
  const [ageState,setAge] = useState(2)
   // Sub changes only when ageState changes
  const sub = useCallback(
    () = > {
      setAge(ageState-1)
    },[ageState],
  )
  // The add function changes only when numState changes
  const add = useCallback(
    () = > {
      setNum(numState+2)
    },[numState],
  )
  return (
    <div>
      <p>num:{numState}</p>
      <p>age:{ageState}</p>
      <hr />
      <MemoHome handle={sub}/>
      <MemoAbout handle={add}/>
    </div>
  )
Copy the code

Usage scenario: useCallback is used when a function in a component is passed to a child component for callback

useMemo

The actual purpose of useCallback is also for performance optimization

  • Usage Scenario 1:
// The Home component is rerendered every time the button is clicked, because the App component's rerendering causes the memory address of Person to change
import React, { memo,useState } from 'react'
const Home = memo((props) = >{
  console.log('Home rendering');
  return (
    <h2>name:{props.person.name}--age:{props.person.age}</h2>)})export default function App() {
  const [show, setshow] = useState(false)
  let person = {name:'zx'.age:15}
  return (
    <div>
      <Home person={person}/>
      <button onClick={()= >setshow(! show)}>changeShow</button>
    </div>)}Copy the code
  • Scenario 1 Solution:
import React, { memo,useMemo,useState} from 'react'
const Home = memo((props) = >{
  console.log('Home rendering');
  return (
    <h2>name:{props.person.name}--age:{props.person.age}</h2>)})export default function App() {
  const [show, setshow] = useState(false)
  let person = useMemo(() = > {
    return {name:'zx'.age:15}}, [])return (
    <div>
      <Home person={person}/>
      <button onClick={()= >setshow(! show)}>changeShow</button>
    </div>)}Copy the code
  • Usage Scenario 2
  • If you are not using useMemo, the function getData will be called again every time the App rerenders
import React,{useMemo, useState} from 'react'
function getData(){
  console.log('getData is called ');
  let data = 0
  for(let i=0; i<1000; i++){ data+=i }return data
}
export default function App() {
  console.log('App component is rendered ');
  const [numState,setNum] = useState(10)
  const [ageState] = useState(55)
  // const data = getData()
  // useMemo allows getData not to be called twice
  const data = useMemo(() = >{
    return getData()
  },[])
  return (
    <div>
      <h2>num:{numState}</h2>
      <h2>age:{ageState}</h2>{/* getData is called again when numState is changed */}<button onClick={()= >{setNum (numState + 1)}} > modify the num</button>
      <h2>data:{data}</h2>
    </div>)}Copy the code

useRef

UseRef can store/find tags or any other data within a component in a function componentCopy the code
  • Introduction of A DOM (or component, but must be a class component) element, storing tag objects, similar to react.createref ()
  • Const container name = useRef()
import React,{useRef} from 'react'
export default function Demo() {
  // Create ref container
  const myRef = useRef()
  function getMsg(){
    // Prints the value inside the element fetched from the ref container
    alert(myRef.current.value)
  }
  return (
    <div>
      <input type="text" ref={myRef}/>
      <button onClick={getMsg}>Get input information</button>
    </div>)}Copy the code
  • Usage two: Save a piece of data that can remain unchanged throughout its lifetime
import React,{useRef} from 'react'
export default function Demo() {
  // myref saves the value, except to manually modify, otherwise will not change
  const myRef = useRef(20)
  function getMsg(){
    // Prints the value inside the element fetched from the ref container
    console.log(myRef.current) / / 20
  }
  return (
    <div>
      <input type="text" />
      <button onClick={getMsg}>Access to information</button>
    </div>)}Copy the code

useImperativeHandle

Before using the useImperativeHandle, you need to know about the forwardRef

forwardRef

  • Function components need to use the forwardRef wrapper to use useRef
  • The wrapped function component can take two arguments, the second of which is ref, and manually bind itself to the element you want
import React, { useRef,forwardRef } from 'react'

function HInput(props,ref){
  After the forwardRef is used, the forwardRef can accept two arguments, the second of which is ref
  return (
    <div>
      <input type="text" ref={ref}/>
    </div>)}// Function components need to use the forwardRef wrapper to use useRef
const NewHInput = forwardRef(HInput)
export default function App()  { 
  const myInput = useRef()
  function change(){
    myInput.current.focus()
  }
    return (
      <div>
        <NewHInput ref={myInput}/>
        <button onClick={change}>Focus on the child component input box</button>
      </div>)}Copy the code

The parent component gets the child component’s DOM and can do whatever it wants.

useImperativeHandle

Just using the forwardRef can do the trick, but the parent can get the dom of the child, so we want to limit the parent’s permissions and just pass in the method that the parent can manipulate the child.

  • Usage:UseImperativeHandle (Pass ref, which is a function, and return an object, whose key is the function name and value is the function)
import React, { useRef,forwardRef,useImperativeHandle } from 'react'

function HInput(props,ref){
  useImperativeHandle(ref,() = >({
    focus:() = >{
      console.log('focus'); }}))return (
    <div>
      <input type="text"/>
    </div>)}const NewHInput = forwardRef(HInput)
export default function App()  { 
  const myInput = useRef()
  function change(){
    myInput.current.focus()
  }
    return (
      <div>
        <NewHInput ref={myInput}/>{/* Click the button to execute your own foucs method */}<button onClick={change}>Focus on the child component input box</button>
      </div>)}Copy the code

Customize the Hook

  • A custom hook is essentially an abstraction of function code logic.
  • A normal function name is preceded by use to use a hook
  • For example, there is a requirement that all components mount updates and unmounts print a single sentence
import React, { useState,useEffect } from 'react'
// Use must be uppercase; // use must be uppercase
function useAddEventListener(component){
  useEffect(() = > {
    console.log(`${component}Component mount update ');
    return () = > {
      console.log(`${component}Component uninstallation '); }})}function Home(){
  useAddEventListener('Home')
  return (
    <div>Home</div>)}function About(){
  useAddEventListener('About')
  return (
    <div>About</div>)}export default function App() {
  const [isShow,setIsShow] = useState(true)
  return (
    <div>
      {isShow &&  <Home/>}
      {isShow &&  <About/>}
      <button onClick={()= >{setIsShow(! IsShow)}} > switch</button>
    </div>)}Copy the code