** Hooks are a new feature in [email protected]. They are fully backward compatible. You can introduce Hooks into your project at any time. Hooks make your code logic cleaner and more focused on write state handling, rather than having the same state handling spread across lifecycles. In addition, Hooks are proposed to enable function components to have the characteristics of class components, improving component performance and code readability. **

React Hooks Code for the class component

Component-based development is one of the most fundamental concepts in current front-end projects. Before Hooks, the React project had two forms of writing components: functional components and class-like components. A function component is just a function, and since there is no this, there is no component instance to speak of, and thus no concept of state and life cycle, it simply renders the UI.

// here is a functional component 🌰 function MyComponent(props) {// A functional component has no state and its data comes from the props passed in by the parent component. In development, the props parameter is typically treated as a deconstructive assignment, such as {name}...... Return (// the DOM structure returned by a functional component (that is, the component UI) <div> <span>{props. Name}</span> </div>) name="Wangyibo"/>Copy the code

So when your component needs to handle state logic, use the Class component. Class components have not only State, but also a life cycle. Each instance of a component, from creation, to execution, to destruction, emits a series of events called component lifecycle functions.Thus, to define a Class component, we need to go through its life cycle and perform different operations in different life cycles.

🌰 import React from 'React' import ReactDOM from 'React '; Class Counter extends React.Component {static defaultProps = {// Set the default value of props name: 'Wangyibo', age:23}; // Call the constructor(props) {super(props); State = {number: 0}} componentWillMount() {console.log(' before the parent component is mounted '); } componentDidMount() {console.log(' Parent component mounted '); } shouldComponentUpdate(newProps, newState) {console.log(' Does the parent need to update '); if (newState.number<15) return true; } componentWillUpdate() {console.log(' parent componentWillUpdate ');} componentWillUpdate() {console.log(' parent componentWillUpdate '); } componentDidUpdate() {console.log(' Parent component updated '); } handleClick = () => {// handleClick = () => {// handleClick = () => {// Use the arrow function. this.state.number + 1 }) }; Render () {console.log('render(parent component mounted)'); return ( <div> <p>{this.state.number}</p> <button onClick={this.handleClick}>+</button> { this.state.number < 10 ? }} reactdom.render (<Counter/>, document.getelementById ('root'));Copy the code

The Class component perfectly embodies the idea of object-oriented programming — you have an instance object, then properties and methods. In other words, we need to take this object and define properties and methods for this. Throughout the component writing process, we use this component instance to retrieve its data and methods. In addition, the lifecycle definition of a class component requires the logic to obtain the state to be spread over the appropriate lifecycle functions. Because of the lifecycle independence, we cannot reuse the state logic well, and the lifecycle definition causes the processing of the state to be cyclical: When our business is complex and there are many states, there will be logic to handle different states in the same life cycle function, and the logic to handle the same state will be spread across different life cycles, resulting in poor code reading and loose logic.

Times change and frameworks need to improve. Each time you write a component, you need to determine whether it is stateful or stateless to choose a functional component or a class component. If you need to add state to stateless components, you need to rewrite stateless components into class components, and class components need to write such a set of templates, code writing is cumbersome. React introduced the concept of Hooks in version 16.8 to solve the problems of cumbersome code writing for class components, difficult reuse of state logic, decentralized processing of state logic, and writing stateful or stateless component switches.

React Hooks New world

In React 16.8, components are written in the simplest and better performing form of function components. Since function components do not have the concept of this instance, Hooks are proposed to fix the situation where we cannot have state in function components. React-hooks do not need this to retrieve data or methods. Instead, they use function closures that execute directly in the component’s global engine. Therefore, in writing components using hooks, we should forget the lifecycle functions, forget the uniform way of manipulating the state property, and instead embrace the global execution functions of hooks.

Using hooks has the following advantages over Class components:

  1. Components are written consistently. Write components as function components without switching and changing between class and function components.
  2. Less code. You don’t need to write a whole set of tedious component templates for class, you don’t need to get data and methods through this, and you don’t need to bind this objects to functions.
  3. Logic is tight. The same state logic can be written together without having to be split into various lifecycle functions.
  4. Easy to reuse. In class components, it is common to reuse component logic in the form of HOC or render props, but there is no way to abstract lifecycle logic. But state logic can be easily encapsulated in hooks for easy reuse.

React hooks To fix the problem with the Class component and make the transition from Class to hooks, React hooks provide the following hooks functions:

Each hooks are discussed in more detail below.

useState

React Hooks to solve the problem of function components having no state, use Estate is proposed by React Hooks to make function components have state.

Usage:

const [state,setState] = useState(initState)
Copy the code

UseState () returns an array of state and a function that updates state. From anywhere within a function component, you can call state directly and change state directly. InitState can be a variety of data types, including string, Boolean, object, or function.

const getDefaultCheckVals = () => {.. } const [defaultCheckVals,setDefaultCheckVals] = useState(getDefaultCheckVals)Copy the code

If you want to execute a function to get the state before render (i.e., to get the default state during initialization), you can write it in useState.

Use the compare

In the Class component, state is set and read as follows:

Class A extents React.component {// The state type is an object in the form of key:value. This. State = {state1: value1, state2: value2, ... }... // Get state, such as this.state.state1... // setState, such as this.setstate ({state1: newValue1})}Copy the code

UseState Hook is used to set state in the function component as follows:

function A(){ const [state1,setState1] = useState(0) const [state2,setState2] = useState([]) ... // Get state, such as state1 // get... // Set state, such as setState1(2)}Copy the code

UseState defines a state that can be called globally in the component without using this. Second, the state type of useState can be any type, whereas the state type of class can only be an object.

Hit the pit

🌰1: Why does passing new parameters to useState not take effect when the component is re-rendered?

const Child = ({name}) => { const [name,setName] = useState(name) return ( <div> name: {name} </div> ) } const parent = () => { const [name,setName] = useState('WYB') return ( <div> <button The onClick = {() = > {elegantly-named setName (' Wangyibo ')}} > modify the name < / button > < Child name = {name} / > < / div >)}Copy the code

Question:

When I click modify name, the name in the page is still not updated. Debugging found that the Child component received the updated props.

😁 answer:

Recall what the React documentation said: during initial rendering, the state returned is the same as the value of the first parameter passed in. In subsequent rerenders, the first value returned by useState will always be the updated state, not the passed parameter value.

🌰2: Modify the state content, why is the component not re-rendered?

Const Child = ({maleGod:{name,age}}) => {console.log(' rendered ') return (<div> name: {name} age: const Child = ({maleGod:{name,age}}) => {console.log(' rendered ') {age} </div> ) } const test = () => { const [maleGod,setMaleGod] = useState({name:'WYB',age:23}) return ( <div> <button </button> <Child maleGod={maleGod}/> </div>)}Copy the code

Question:

The value of state is reset each time, but the content on the page does not change.

😁 answer:

For function components, the component is rerendered whenever the props or state changes. However, for real changes, the component will not be rerendered if your set state is the same as last time or if the object’s reference address is unchanged. In general, the easiest place to tread is with objects. Just as []===[] is always false, when setting the state of an object type, remember to assign a new object. There are two common ways to do this:

//方式一,采用es6的对象解构
{...obj}
//方式二,采用Object.assign(),复制新对象
Object.assign({},obj,{...}
Copy the code

Modify 🌰 above as follows:

. <button onClick={()=>{setMaleGod({... </button> </button>...Copy the code

To optimize the

Take the previous example:

const getDefaultCheckVals = () => {.. } const [defaultCheckVals,setDefaultCheckVals] = useState(getDefaultCheckVals())Copy the code

In the code above, the getDefaultVals function is executed once each time the component is rerendered. Therefore, in order for the function that sets the default value to be executed only once initially, we can rewrite it as a callback function:

const getDefaultCheckVals = () => {.. } const [defaultCheckVals,setDefaultCheckVals] = useState(()=>getDefaultCheckVals())Copy the code

useEffect

React hooks to solve the problem that it is difficult to reuse logic from lifecycle functions in Class components, and that logic handling the same state is spread across multiple lifecycle functions, React hooks developed useEffect to allow function components to handle side effects that are originally in the lifecycle.

Usage:

const A = ()=>{
    const showLog = ()=>{
        console.log('myLog')
    }
    useEffect(()=>{
        docuemnt.getElementByID('btn').addEventListener('click',showLog)
        return ()=>{
        docuemnt.getElementByID('btn').removeEventListener('click',showLog)
    }
    },[])

    return (
        <button id='btn'>button</button >
    )

}
Copy the code

UseEffect () takes two arguments: the first mandatory argument is funciton, which handles side effects performed after the DOM node is mounted, completing the side effects performed in componentDidMount and componentDidUpdate functions. The second optional argument is an array that represents the dependencies — when the dependencies in the array change, the useEffect side effect is reexecuted. If no dependencies are passed, i.e. an empty array, the useEffect dependency never changes. The useEffect side effects are performed only when the component is rendered for the first time. When no second argument is passed, indicating that there are no dependencies, the useEffect side effects are performed every time the component renders. (The dependencies are shallow comparisons with object.js ())

Comparison of use:

Using the example in the above usage, using a lifecycle function in a class handles the following side effects:

class A extents React.component {
   ...
    componentDidMount(){
        docuemnt.getElementByID('btn').addEventListener('click',showLog)
    }

    componentDidUnMount(){
        docuemnt.getElementByID('btn').removeEventListener('click',showLog)
    }
  ...
}

Copy the code

Compared to the way side effects are written in class components versus functional components, useEffect makes the business logic more clustered and the code more readable and maintainable than the decentralized business logic of a class’s lifecycle. UseEffect is a nice way to simplify code when the business is more complex.

Hit the pit:

🌰1: The state change triggers rerendering, causing the new variable to be redefined, which triggers the useEffect infinite loop.

Const test = ()=>{const [lists,setLists] = useState([]) const defaultValue = Object UseEffect (()=>{doSomeThings() // This has the business logic to handle the state. },[defaultValue]) }Copy the code

Question:

Why did doSomething() enter a wireless loop execution? (infinite)

😁 answer:

Since a change in state triggers a component re-rendering, which in the case of a function component means a re-execution of the entire function, this causes defaultValue to be redefined as a new object instance, and since the new object must not be equal (the reference address has changed), This results in useEffect executing side effects due to a dependency change, which in turn changes the state, leading to a wireless loop. Therefore, in similar scenarios as above, we can change the dependency to a specific attribute value, or further judge the dependency through the if condition in useEffect, so as to determine whether doSomeThings() needs to be executed.

🌰2: useEffect closure causes the state value to remain unchanged

const test = ()=>{
    const [count,setCount] = useState(0)

    useEffect(()=>{
        const timer = setInterval(()=>{
            setCount(count+1)
        },1000)
        return ()=>clearInterval(timer)
    },[])

    return (
        <div>{count}</div>
    )
}
Copy the code

Question:

The change of count in the timer does not take effect and 1 is displayed continuously.

😁 answer:

Since useEffect has no dependencies, the side effects in useEffect are performed only once when the component is first rendered, and the states in useEffect are the initial values. Because of the useEffect closure, the timer is used to obtain the initial count of 0 every time, so the final page display is always 1.

// There are two ways to change the code to get the correct result. // The state is maintained in its local function. Each call to setCount directly retrieves its internal state, so the result is as expected. . useEffect(()=>{ const timer = setInterval(()=>{ setCount( count => count+1 ) },1000) return ()=>clearInterval(timer) } [])... -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- / / way 2 add state variables to dependency / / dependency state change, The state in each side effect is the latest value. . useEffect(()=>{ const timer = setInterval(()=>{ setCount(count+1) },1000) return ()=>clearInterval(timer) },[count]) ...Copy the code

Optimization:

The optimization of useEffect is mainly based on the definition when defining useEffect side effects:

  1. When uninstalling components, remove side effects that need to be removed, such as bound event listeners, timers, and so on;
  2. To prevent the component from executing side effects every time it renders, simply pass in the second dependency array argument. Make sure that the dependency array contains variables in the side effects function that change over time and are used in the side effects;
  3. To make it clear what variables your side effect contains, move the externally defined business handler function inside the effect function.
  4. Functions that do not depend on state or internal variables can be separated from components and encapsulated as utility functions.
  5. A function that depends on an internal variable can be pulled out of effect so that effect depends on its return value.
  6. If the logic is too complicated, you can add the function to the effect dependency, but be careful to wrap the function in useCallback so that effect is not called every time the rendering component is called.
  7. It is best not to use object type data as a dependency, to prevent the same data only reference address is different, and lead to repeated rendering problems;

So far, two hooks, useState and useEffect: one to handle the state and one to replace the lifecycle function, basically do most business project development. However, in order to reduce application performance problems caused by component re-rendering and recalculation, and to improve code readability and reduce layer upon layer transmission of component props, appropriate hooks should be flexibly selected during project development to optimize component performance and reduce nested transmission of components.

useLayoutEffect

UseLayoutEffect is a hook method with a similar name to useEffect. However, useEffect is used 90% of the time, whereas in some cases it is necessary to use useLayoutEffect (for example, some side effects need to be called synchronously, which can be performed synchronously after DOM updates). The difference between useEffect and useLayoutEffect is:

  1. UseEffect does not block browser rendering, whereas useLayoutEffect does.
  2. UseEffect is executed after the browser renders, useLayoutEffect is executed after the DOM update is complete and before the browser draws.

Use the standard useEffect whenever possible to avoid blocking visual updates.

useCallback

UseCallback is used to avoid unnecessary rendering, mainly for caching functions. Typically, when a child calls a parent’s method, the method is wrapped in a useCallback.

Usage:

. Const handleSearch = useCallback(()=>{// a series of business logic})... <Child handleSearch={handleSearch}/>Copy the code

UseCallback () takes two arguments: the first mandatory argument is the defined callback function used for the component’s event handling. It is defined but not run during the component’s rendering. The second optional argument is an array of dependencies that control whether the callback function needs to be redefined.

💡 note 💡 : When the callback uses state data, always remember to add the state variable to the dependency so that the state changes and the callback function is updated with the latest state value. Otherwise, the state variable in the callback function is always the initial value of the first rendering.

Examples of optimized components:

// test1: const test1 = ()=>{... return ( <Button onClick={()=>{... }} />)} // Question: The test1 code directly passes the business logic to Button in the form of an anonymous function. Apart from coupling the business logic to the UI, the problem with this form is that every time the Test component is re-rendered, a new and repeated anonymous arrow function is generated. Causes the onClick property of the Button component to change, Triggering the Button component of rendering (rendering the results did not change) -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- / / test2: Decouple business logic and UI components const test2 = ()=>{const [count,setCount] = useState(0) const [initVal, setInitVal] = useSatte('') const onChange = (e) => { setInitVal(e.target.value) } const addCount = () => { Return (<Input onChange={onChange} value={initVal}/> <button onClick={addCount}> {count}</button>)} // Problem: in test2 code, the business logic is removed and the reference address is passed to the component. Test2 will be re-rendered when the count state value is changed. The re-rendering of function components is a re-execution of the entire function, so a new onChange function is redefined. This causes the onChange property of the Input component to change (because the function is an object type and each new function reference address is different), which causes the Input component to render unnecessarily (because clicking on the button only changes the value of count, Props are not related to the Input changes) -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- / / test3: Const test3 = ()=>{const [count,setCount] = useState(0) const [initVal, SetInitVal] = useSatte(") const onChange = useCallback((e) => {setInitVal(e.target.value)},[]) The component also redefines the callback function each time it renders. Since the callback function does not depend on state, it simply passes the empty array dependency, Const addCount = useCallback(() => {setCount(count+1)},[count]) // Because the callback uses a state variable, we need to pass that state as a dependency, So that each callback gets the latest state instead of the initial render state. Return (<Input onChange={onChange} value={initVal}/> <button onClick={addCount}> {count}</button>)} // Advantage: with the useCallback wrapped callback function, the child component does not need to render due to the parent component's re-rendering, thus reducing rendering and improving component performance.Copy the code

😺 Others: Commonly used in conjunction with useCallback is react.Memo (), which is used to cache components and prevent unnecessary rendering of components just because the reference address of one of the props changes. This is a shallow comparison, and it is comparing the entire props object. If you want to control the comparison process, pass in a second argument to your custom comparison function (which takes two arguments: prevProps,nextprops). Return true, do not re-render; Return false, rerender)

Because a change in props or state causes the component to re-render; And parent component rendering, because is the function component, so the whole function is to perform a, make the child components will perform a again, but the child components of props and no change, then child components made unnecessary to perform, so here you can use the React. The memo to wrap the component, reduce child components unnecessary updates. In addition, if the child components of props contains the parent component method, may be because the parent component rendering to generate a new object instance, lead to reference address change, leading to update child components, so it need to use useCallback will wrap this method, the ways to reduce unnecessary redefined, thus reducing components of rendering.

useMemo

UseMemo is used to avoid unnecessary double calculation. It is mainly used to cache some complex calculation results and prevent the complex calculation process from being re-executed every time the component is rendered. Similar to the calculation properties in Vue, it is directly executed during the component rendering process.

Usage:

Const sum = useMemo(()=>{// series of calculations},[count])Copy the code

UseMemo () receives two parameters: the first mandatory parameter is a function that is used to perform the corresponding calculation, return the new value after calculation, the value will be cached (also can not return a value, a simple cache a function’s operation process, the dependency doesn’t change, this function will not run again, suitable for processing of higher-order functions scenario). The second optional argument is an array of dependencies, which are re-executed whenever the value of the dependency changes. If this dependency is not provided, useMemo evaluates the new value every time it renders.

Examples of optimized components:

const App = () => { const [count1,setCount1] = useState(0) const [message,setMessage] = useState('abcdefg') UseEffect (()=>{const timer = setInterval(()=>{setCount1((count1)=>count1+1)) },1000) return ()=>clearInterval(timer)},[]) const reverse = ()=> {const reverse = ()=> { Console.log (message) return message.split(" ").reverse().join(" ")} // get the reverse string. Because of the timer defined earlier, the component is re-rendered every second, so the function that calculates the inversion string is also re-invoked every second. If the computation is large, performing it every time can be costly. const reversedMessage = reverse() const doChangeStr = ()=>{ setMessage(message=>message+Math.ceil(Math.random()*10)) } Return (<div className="App"> <div>{count1}</div> <button onClick={doChangeStr}> {reversedMessage}</p> </div>); } -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- / / value useMemo place to the const App () = = >  { const [count1,setCount1] = useState(0) const [message,setMessage] = useState('abcdefg') useEffect(()=>{ const timer =  setInterval(()=>{ setCount1((count1)=>count1+1) },1000) return ()=>clearInterval(timer) },[]) // ReversedMessage is computed for the first rendering of the component, and then refreshed for subsequent components every second. ReversedMessage is read from the cache, not recalculated. ReversedMessage is recalculated only when the dependency message changes const reversedMessage = useMemo(()=>{console.log(message) return message.split('').reverse().join('') },[message]) const doChangeStr = ()=>{ setMessage(message=>message+Math.ceil(Math.random()*10)) } return ( <div className="App"> <div>{count1}</div> <button OnClick ={doChangeStr}> modify string </button> <p> original string {message}</p> <p> </div>); }Copy the code

useReducer

UseReducer is an alternative to useState and is used in a similar way. UseState is the basic hooks used to define the initial state, but useReducer is better than useState in complex business cases where there are many substates of a state.

Usage:

Const [state,dispatch] = Reducer(Reducer,initState,init)Copy the code

Similar to the work rule of REdux, the rule that changes state only triggers the action object, which is received by reducer and the state is updated according to the type of the action. Therefore, useReducer() receives two arguments: the first mandatory argument is a reducer function of the form (state, action) => newState, and the second mandatory argument is the initial value of state. The return value is an array with the first item being state and the second item being a dispatch dispatch function that triggers the action. The third argument is an optional value to lazily provide the initial state, and we can use an init function to calculate the initial state/value instead of the displayed provided value. The init function needs to be passed in as the third argument to the useReducer, so that the initial state will be set to init(initState), which is handy if the initial value may be different, and eventually the calculated value will be substituted for the initial value.

Examples of optimized components:

const UseReducerTest = () => { const [val, setVal] = useState(0) const doAdd = ()=> setVal(val+1) const doSub = ()=> setVal(val-1) const doMul = ()=> setVal(val*2)  const doDiv = ()=> setVal(val/3) return ( <div> <button onClick={doAdd}>+</button> <button onClick={doSub}>-</button> <button onClick={doMul}>x</button> <button onClick={doDiv}>/</button> However, if the service logic is complex and there are many actions to modify the status, using useReducer is better. UseReducer centrally manages status, makes it easier to maintain status, and centralizes service logic. -------------------------------------------------------------------------------- const reducer = (state,action)=>{ switch (action.type) { case 'addition': return state+1; case 'subtraction': return state-1; case 'multiplication': return state*2 case 'division': return state/3; default: return state; } } const UseReducerTest = () => { const [val, dispatch] = useReducer(reducer,0) return ( <div> <button onClick={()=>{dispatch({type:'addition'})}}>+</button> <button onClick={()=>{dispatch({type:'subtraction'})}}>-</button> <button onClick={()=>{dispatch({type:'multiplication'})}}>x</button> <button OnClick = {() = > {dispatch ({type: 'division'}}} > / < / button > current val as: {val} < / div >)}Copy the code

useContext

UseContext is primarily a technique for sharing global state between components (value passing across components), reducing layer upon layer nesting when components pass values and avoiding unnecessary rendering due to props changes. When the value it provides changes, all the child components it contains are rerendered, and there is no way to avoid this. Context only places necessary state that is shared by most components. For very expensive components, it is recommended to get the Context data at the parent level and pass it in through props

Usage:

const value = useContext(MyContext)
Copy the code

UseContext receives a context object, created by React. CreatContext, and returns the current value of the context. When used in a component, the context value taken by the component is determined by the < MyContext.provider > value prop of the upper-layer component closest to the current component. When the most recent <MyContext.Provider> update is made to the component’s upper layer, the Hook triggers a rerender and uses the latest context value passed to MyContext Provider. Even if the ancestor uses React. Memo or shouldComponentUpdate, it will be rerendered when the component itself uses useContext

Examples of optimized components:

const Content = (props) => { return ( <div> <span> {props.text} </span> </div> ) } const Child = (props) => { return ( <div> <Content text={props.text} /> </div> ) } const UseContextTest = () => { const [text, setText] = useState('hello');  Return (<div> <Child text={text} /> </div>)} // Props are used to pass values across components until the target component is reached. This creates a cumbersome nesting hell and causes every component in the component tree to be re-rendered because of changes in props. -------------------------------------------------------------------------------- const dataOrigin = { text:'hello' } const ShareData = React.createContext(dataOrigin) const Content = () => { const data = useContext(ShareData) return ( <div> <span> {data.text} </span> </div> ) } const Child = () => { return ( <div> <Content/> </div> ) } const UseContextTest = ()=>{ return ( <ShareData.Provider value={{text:'hahaha'}}> <Child/> </ShareData.Provider> ) }Copy the code

useRef

Refs are primarily used to get DOM nodes (references to DOM objects, which are real references, not value copies) and to call back the internal state or methods of the child in the parent component. UseRef () is a method to get a ref and can only be used by function components. UseRef returns a mutable REF object, but that object remains constant throughout the life of the component. It has a current property that holds the mutable values (states or methods) of the REF object, which means React sets the.current property of the ref object to the corresponding DOM node.

Usage:

  const tableRef = useRef()
Copy the code

Refs are typically used to manipulate peers or child components.

Examples from the official website:

function TextInputWithFocusButton() { const inputEl = useRef(null); Const onButtonClick = () => {// 'current' points to the text input element inputel.current.focus () mounted to the DOM; }; return ( <> <input ref={inputEl} type="text" /> <button onClick={onButtonClick}>Focus the input</button> </> ); }Copy the code

useImperactiveHandle

This is mainly used for pass-through refs, and references to child components can then be obtained in the parent component. Instead of using imperative code like ref directly, use it with the forwardRef to customize the instance values exposed to the parent component. Currently in the project

Example usage:

const { useCallback } = require("react")
const Child = forwardRef(({ prod1,prod2 }, ref) => {
    ...
    useImperativeHandle(ref, () => ({
        refresh: () => {
         // doSomethings
         ...
        }
      }))
    ...
}
const parent = ()=>{
    const childRef = useRef()
    const refreshTable = useCallback(()=>{
        childRef?.current?.refresh()
    },[])
    ...
    return (
        <div>
            <Button onClick={refreshTable}/>
            <Child ref={childRef}>
        </div>
    )
}
Copy the code

useDebugValue