The React zh-hans.reactjs.org/docs/hooks- Hooks Chinese website…

React Hooks

Built-in Hook describe
useState Maintaining state
useEffect Complete side effects
useContext Using shared State
useReducer An alternative to useState, similar to Redux
useCallback Caching functions and their references
useMemo Caching functions and their values
useRef Access to the DOM
useImperativeHandle Use the values and methods exposed by the child component
useLayoutEffect Completes the side effect operation. Unlike useEffect, this hook blocks the browser drawing

useState

Add internal state to the React function component

import React, { useState } from 'react';

export default() = > {const [count, setCount] = useState(0);
  
  return (
    <>
      <h1>count: {count}</h1>{/* Common update */}<button onClick={()= >setCount(count + 1)}>add</button>{/* Functional update */}<button onClick={()= >setCount(prevCount => prevCount + 1)}>add</button>
    </>
  );
};
Copy the code

useEffect

If you’re familiar with React Class lifecycle functions, you can think of useEffect Hook as componentDidMount, ComponentDidUpdate and componentWillUnmount.

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

export default() = > {const [count, setCount] = useState(0);
  
  useEffect(() = >{
    console.log('useEffect executes: componentDidMount');
  }, [])
  
  useEffect(() = >{
    console.log('useEffect executes: componentDidUpdate');
  }, [count])
  
  useEffect(() = >{
    return () = >{
      console.log('useEffect executes: componentWillUnmount'); }}, [])return (
    <>
      <h1>count: {count}</h1>
      <button onClick={()= >setCount(count + 1)}>add</button>
    </>
  );
};
Copy the code

useContext

Context provides a way to share values between components without explicitly passing props layer by layer through the component tree

import React, { useContext } from 'react';

const data = {
  name: 'falco'.age: '18'
}

const ComponentContext = React.createContext(data);

const Child = () = > {
  const { name, age } = useContext(ComponentContext);
  
  return (
    <div>
      {name} - {age}
    </div>)}const Parent = () = > {
  return (
    <>
      <ComponentContext.Provider value={data}>
        <Child/>
      </ComponentContext.Provider>
    </>)}export default Parent;
Copy the code

useReducer

Is an alternative to useState. Receive a Reducer of the form (state, action) => newState and return the current state and its matching dispatch method

import React, { useReducer } from 'react';

const initialState = [
  { id: 1.name: 'Joe' },
  { id: 2.name: 'bill'},]const reducer = (state, action) = > {

  const { type, payload } = action;
  
  switch(type){
    case 'add':
      return [...state, payload];
    case 'update':
      return state.map(item= >item.id === payload.id ? {... item, ... payload } : item);case 'remove':
      return state.filter(item= >item.id ! == payload.id);case 'clear':
      return []
    default:
      throw new Error()}}export default() = > {const [state, dispatch] = useReducer(reducer, initialState);
  
  return (
    <>
      List: {JSON.stringify(state)}
      <div>
        <button onClick={()= >Dispatch ({type: 'add', content: {id: 3, name: 'Cathy'}})} > add</button>
        <button onClick={()= >Dispatch ({type: 'update', payload: {id: 3, name: 'x6'}})}>update</button>
        <button onClick={()= >dispatch({type: 'remove', payload: { id: 1 }})}>remove</button>
        <button onClick={()= >dispatch({type: 'clear', payload: { id: 1 }})}>clear</button>
      </div>
    </>)}Copy the code

useCallback

Both useCallback and useMemo can cache a reference or value to a function, but in a more subtle sense useCallback caches a reference to a function, useMemo caches the value of calculated data

import React, { 
  useState,
  useRef,
  useEffect,
  useCallback
} from 'react';

const usePrevProps = value= > {

  const ref = useRef(null)
  
  useEffect(() = >{
    ref.current = value
  }, [])
  
  return ref.current
}

const Button = React.memo(({ title, onClick }) = > {
  console.log('render button');
  return <button onClick={onClick}>{title}</button>;
});

export default() = > {const [count, setCount] = useState(0);
  const [total, setTotal] = useState(0);
  
  // const handleCount = () => setCount(count + 1);
  const handleCount = useCallback(() = > setCount(count + 1), [])
  const handleTotal = () = > setTotal(total + 1);
  
  const prevHandleCount = usePrevProps(handleCount);  
  
  console.log('Are the two handlers equal:', prevHandleCount === handleCount); // true
  
  return (
    <div>
      <div>Count is {count}</div>
      <div>Total is {total}</div>
      <br />
      <div>
        <Button title={'add Count'} onClick={handleCount} />
        <Button title={'add Total'} onClick={handleTotal} />
      </div>
    </div>)}Copy the code

useMemo

You pass in the create function and the dependency array as arguments to useMemo, which recalculates memoized values only when a dependency changes. This optimization helps avoid costly calculations every time you render. If the dependency array is not provided, useMemo evaluates the new value each time it renders.

import React, { 
  useState,
  useRef,
  useEffect,
  useCallback,
  useMemo
} from 'react';

const usePrevProps = value= > {
  const ref = useRef(null)
  
  useEffect(() = >{
    ref.current = value
  }, [])
  
  return ref.current
}

export default() = > {const [count, setCount] = useState(0);
  const [total, setTotal] = useState(0);
  
  UseMemo's first function is executed when the count variable changes
  const calcValue = useMemo(() = >{
    return Array(100000)
      .fill(' ')
      .map(v= > v);
  }, [count])
  
  const handleCount = () = > setCount(count + 1);
  const handleTotal = () = > setTotal(total + 1);
  
  const prevCalcValue = usePrevProps(calcValue);  
  console.log('Are the two calculations equal:', prevCalcValue === calcValue); // false
  
  return (
    <div>
      <div>Count is {count}</div>
      <div>Total is {total}</div>
      <br />
      <div>
        <button onClick={handleCount}>Increment Count</button>
        <button onClick={handleTotal}>Increment Total</button>
      </div>
    </div>)}Copy the code

useRef

UseRef returns a mutable ref object whose.current property is initialized as the passed parameter (initialValue). The ref object returned remains constant throughout the life of the component.

import React, { useRef } from 'react';

export default() = > {const inputEl = useRef(null);
  
  const handleFocus = () = > {
    // 'current' points to the text input element mounted to the DOM
    inputEl.current.focus();
  }
  
  return (
    <>
      <input ref={inputEl} />
      <button onClick={handleFocus}>Focus</button>
    </>)}Copy the code

useImperativeHandle

You can have the parent component call properties/methods exposed by the child component. UseImperativeHandle should be used together with the forwardRef

import React, { 
  useState,
  useRef, 
  forwardRef, 
  useImperativeHandle 
} from 'react';

const Child = forwardRef((props, ref) = > {
  const inputRef = useRef(null);
  const [value, setValue] = useState(0);
  
  useImperativeHandle(ref, () = >({
    focus: () = > {
      inputRef.current.focus()
    },
    setValue
  }))
  
  return (
    <>
    <div>child-value: {value}</div>
    <input ref={inputRef}/>
    </>)})export default() = > {const inputEl = useRef(null);
  
  const handleFocus = () = > {
    inputEl.current.focus();
  }
  
  const handleAdd = () = > {
    inputEl.current.setValue(val= > val + 1)}return (
    <>
      <Child ref={inputEl} />
      <button onClick={handleFocus}>Focus</button>
      <button onClick={handleAdd}>add</button>
    </>)}Copy the code

useLayoutEffect

Effect is called synchronously after all DOM changes. You can use it to read DOM layouts and trigger rerenders synchronously. The update schedule inside useLayoutEffect is flushed synchronously before the browser executes the drawing, which means it blocks the browser drawing. UseEffect whenever possible to avoid blocking visual updates.

import React, { 
  useState,
  useRef, 
  useEffect, 
  useLayoutEffect 
} from 'react';

const UseEffect = () = > {
  const box = useRef(null);
  
  useEffect(() = >{
    box.current.style.backgroundColor = 'green';
  }, [])
  
  return (
    <div
      ref={box}
      style={{
        width: 200.height: 200.backgroundColor: 'red'}} >
    UseEffect
    </div>)}const UseLayoutEffect = () = > {

  const box = useRef(null);
  
  useLayoutEffect(() = >{
    box.current.style.backgroundColor = 'green';
  }, [])
  
  return (
    <div
      ref={box}
      style={{
        width: 200.height: 200.backgroundColor: 'pink'}} >
    UseLayoutEffect
    </div>)}export default() = > {const [visible, setVisible] = useState(false);
  
  return (
    <div className='App'>
      <button onClick={()= >setVisible(! Visible)}> Mount/unmount components</button>
      {
        visible && (
          <div style={{ display: 'flex' }}>
          <UseEffect />
          <UseLayoutEffect />
          </div>)}</div>)}Copy the code