Introduction to the

  • Hook allows you to use state and other React features without writing a class. When you use “function declaration component”, you use Hook

  • Features:

    • Totally optional. You can try hooks in some components, but you don’t have to learn or use hooks if you don’t want to
    • 100% backward compatibility: Hook does not contain any destructive changes
    • Currently available: Hooks have been released in V16.8
    • There are no plans to remove classes from React
    • Hook doesn’t affect your understanding of React concepts
      • Hooks provide a more straightforward API for known React concepts: props/State/Context/refs and lifecycle

motivation

  • It is difficult to reuse state logic between components:

    React does not provide a way to “attach” reusable behavior to components; Use render props and higher-order components to solve this problem. But such scenarios require reorganizing your component structure, which can be cumbersome and make your code difficult to understand

  • Components composed of providers, consumers, advanced components, render props, and other abstraction layers form a nested hell

  • Use hooks to extract state logic from components so that it can be individually tested and reused. Hooks allow you to reuse state logic without modifying the component structure

  • Complex components become difficult to understand

    Each lifecycle often consists of unrelated logic that is gradually overwhelmed by state logic and side effects, where code that is related and needs to be modified is split apart, while completely unrelated code is grouped together in the same method. This is very buggy and leads to logical inconsistencies

    Hooks break down the interrelated parts of a component into smaller functions (such as setting up subscriptions or requesting data) rather than enforcing partitioning by lifecycle. You can also use Reducer to manage the internal state of components and make them more predictable.

  • Hard to understand class

    Hook allows you to use more React features in non-class situations.

    Hooks and existing code work together, and you can use them incrementally

An overview of

  • A Hook is a function that lets you “Hook” features like React state and lifecycle into a function component
  • Hooks cannot be used in class components — this allows you to use React without using class
  • Hooks are saved in function scope for easy accessstate/propsVariables such as
  • Hook uses THE JS closure mechanism instead of introducing the React API when JS already provides a solution.

state Hook

  • Call it in the function component to add some internal state to the component. React will retain this state for repeated rendering
  • useStateReturns a pair of values: the current state and a function that lets you update it, which you can call in an event handler or some other place
  • useStateThe only argument is the initial state. This initial parameter is only used for the first rendering.
  • State hooks can be used multiple times within a component

Effect Hook

  • React will wait for the browser to finish rendering the canvas before delaying the calluseEffect
  • useEffectIs an Effect Hook, which adds the ability to manipulate side effects to function components.
    • Merge classcomponentDidMount componentDidUpdatecomponentWillUnmount
    • By using hooks, you can group related side effects within components rather than splitting them into different lifecycle functions
  • Perform data fetch, subscribe, or manually modify the DOM in the React component. We collectively refer to these actions as “side effects,” or simply “effects.”
  • Because side functions are declared inside the component, they can access the props and state of the component
  • By default, React calls side effects after every render — including the first one
  • A side effect function can also specify how to “clear” the side effect by returning a function
  • UseEffect can be used multiple times in components

Hook usage rules

Hooks are JS functions, but there are two additional rules for using them:

  • A Hook can only be called on the outermost layer of a function. Do not call in loops, conditional judgments, or subfunctions.
  • You can only call a Hook in the React function component. Do not call from other JS functions (custom hooks can also be called)

Customize the Hook

  • Custom hooks allow you to reuse some of the state logic between components without adding them. To replace the two main alternatives: high-level components and Render props
  • We just need to extract the Hook logic that calls useState and useEffect into a custom Hook.
  • The same custom Hook can be called multiple times within a single component (each call of a Hook has a completely independent state)
  • Custom hooks are more of a convention than a feature. If the function name starts with “use” and calls other hooks, we say it is a custom Hook (easier to find the problem in a checker such as the Linter plugin)

Other Hook

  • UseContext lets you subscribe to React and Context without using component nesting
  • UseReducer allows you to manage complex local states of components using reducer

useState

  • useStateAnd the class insidethis.stateThe functionality is exactly the same. Normally, variables “disappear” after the function exits, while variables in state are retained by React
  • The only argument in the useState() method is the initial state (which, unlike class, can be an underlying data type, not necessarily an object).
  • UseState () returns the current state and the function that updates the state, both of which need to be retrieved in pairs
const [count , setCount] = useState(0);
The JS syntax is called array deconstruction, which means we create two variables at the same time. The first variable returns the first value, and the second variable returns the second value.
Copy the code

Effect Hook

  • Effect Hook allows you to perform side effects in function components.
    • Fetching data, setting up subscriptions, and manually changing the DOM in the React component are all side effects
  • Each rerender generates a new effect to replace the previous one
    • In a sense, an effect is more like a part of a render result — each effect ‘belongs’ to a particular render.
    • The function passed to Effect will change with each rendering, so we can get the latest data value in Effect without worrying about its expiration
  • UseEffect is executed after every render (after the first render and after every update)
  • Can put theuseEffectThe hooks ascomponentDidMountcomponentDidUpdatecomponentWillUnmountThe combination of these three functions. (Avoid writing duplicate code in multiple lifecycle functions)
  • There are two common side effects operations in the React component: those that need to be cleaned and those that do not
    • Effects that don’t need to be cleaned: Run some extra code after React updates the DOM. After these operations are done, you can ignore them (e.g. sending network requests, manually changing the DOM, logging).
    • Effects to clean up: Such as subscribing to external data sources, cleaning is important to prevent memory leaks
      • Each effect can return a cleanup function. This brings together the add and subscribe logic, which is all part of Effect
      • React performs cleanup operations when components are uninstalled. Effect is executed on every render. This is why React cleans up the previous effect before executing the current effect. Each time a new effect is re-rendered.

To strengthen

  • Separation of concerns is achieved using multiple effects
    • Hooks allow us to separate code according to its purpose, rather than life cycle functions. React calls each effect in the component in the order in which it was declared
    • Solve the problem that class lifecycle functions often contain unrelated logic but split the related logic into several different methods
  • Run Effect every time you update it
    • UseEffect defaults to cleaning up the previous effect before calling a new one. Avoid memory leaks in component functions that cause Bug problems
  • Performance optimization through passing Effect
    • In some cases, performing cleanup or effect after every render can cause performance problems. If certain values do not change between rerenders, you can tell React to pass a call to Effect by passing an array as the second optional argument to useEffect.

    • The same applies to effects that have a clean operation

    • Make sure the array contains all variables that will change over time to the external scope and be used in effect, otherwise your code will reference old variables from previous renderings

    • If you want to execute effect only once (only when the component is mounted and unmounted), you can pass an empty array [] as the second argument.

Rules of the Hook

  • Use hooks only at the top level
    • Make sure the hooks are called in the same order every time you render, keeping the Hook state correct
      • React relies on the sequence of Hook calls to determine which state corresponds to which useState
      • Using hooks not at the top level can break the order and cause the state to be buggy
    • Never call hooks in loops, conditions, or nested functions. Be sure to always call them at the top of your React functions and before any returns
  • Only the React function calls the Hook
    • Ensure that the component’s state logic is clearly visible in the code
    • Do not call a Hook in a normal JS function

Hook API

Based on the hooks

useState

const [count , setCount] = useState(0);
Copy the code
  • During initial rendering, the state returned is the same as the value of the first parameter passed in
  • The setState function is used to update state. It receives a new state value and queues a rendering of the component.
    • Two usages: ordinary and functional
      • SetCount (x): Pass the parameter value directly and set the state
      • SetCount (x => x+1) calls the function to change the state
  • The identity of the setState function is stable and does not change when the component is re-rendered
  • If your update function returns exactly the same value as the current state, subsequent rerenders will be skipped entirely
  • UseState does not automatically merge update objects
    • The effect of merging updated objects can be achieved by using a functional setState in conjunction with the expansion operator
    return{... prevState , ... updatedValues}Copy the code
  • Lazy initial state: If the initial state needs to be computed by complex calculations, you can pass in a function that computes and returns the initial state, which is called only during the initial render
  • Skip state updates: When you call the update function of the state hook and pass in the current state, React skips rendering and effect execution of the child components
    • React uses the object. is comparison algorithm to compare states
    • React may still need to render the component before it can be skipped
    • If you are performing expensive calculations during rendering, you can use useMemo for optimization

useEffect

useEffect(didUpdate)
Copy the code
  • The Hook receives a function that contains imperative code that may have side effects
  • For side effects, use useEffect. The function assigned to useEffect is executed after the component is rendered to the screen.
  • By default, effect is executed at the end of each render round, but you can choose to have it executed only when certain values change
  • To prevent memory leaks, the cleanup function is executed before the component is unloaded
    • If the component renders multiple times (as it usually does), the previous effect is cleared before the next effect is executed
  • The function of useEffect andComponentDidMount, componentDidUpdateIt is executed after the browser has finished laying out and drawing
  • React provides extra for thisuseLayoutEffectHook to handle effects that cannot be delayed. It has the same structure as useEffect except for the timing of the call (similar to the difference between passive and active listening events).
  • You can pass useEffect a second argument, which is the array of values that Effect depends on and will only be re-rendered if the array changes.
    • All values referenced in the effect function should appear in the dependency array, because the dependency array is not passed to the Effect function as an argument
    • In the future, compilers will get smarter and it will be possible to create arrays automatically.

useContext

const value = useContext(MyContext);
Copy the code
  • Receives a context object (the return value of React. CreateContext) and returns the current value of the context.
  • The argument to useContext must be the context object itself:
    • Right: useContext (MyContext)
    • Error: useContext (MyContext. Consumer)
    • Error: useContext (myContext. The Provider)
  • The current context value is determined by the < MyContext.provider > value prop of the upper-layer component closest to the current component
  • Ancestors using React. Memo or shouldComponentUpdate will also be rerendered when the component itself uses useContext.

Additional hooks

Additional hooks are variations of the base hooks in the previous section, and some are only used in special cases

useReducer

const [state ,dispatch] = useReducer(reducer , initialArg , init);
Copy the code
  • An alternative to useState. It receives a Reducer of the form (state, action) => newState and returns the current state and its accompanying dispatch method.

  • Using useReducer also provides performance optimization for components that trigger deep updates because you can pass dispatches to child components instead of callbacks.

  • Lazy initialization: The init function is passed in as the third argument to the useReducer, so that the initial state is set to init(initialArg).

  • Skip Dispatch: If the return value of the Reducer Hook is the same as the current state, React skips the rendering of the child components and the execution of the side effects.

    • React uses the object. is comparison algorithm to compare states.
  • React ensures that the identity of the Dispatch function is stable and does not change when the component is re-rendered.

useCallback

const memoizedCallback = useCallback(
 () = > {
   doSomething(a, b);
 },
 [a, b],
);

Copy the code
  • Returns a Memoized callback function.

  • UseCallback (fn, deps) is equivalent to useMemo(() => FN, deps).

  • The callback function is updated only when a dependency changes.

  • Used when you pass callback data to children that are optimized and use reference equality to avoid unnecessary rendering (e.g. ShouldComponentUpdate).

useMemo

const memoizedValue = useMemo(() = > computeExpensiveValue(a, b), [a, b]);
Copy the code
  • Returns an memoized value.

  • 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.

  • Functions passed into useMemo are executed during rendering.

    • Do not do anything inside this function that is not related to rendering
    • Operations such as side effects are useEffect, not useMemo.
  • If the dependency array is not provided, useMemo evaluates the new value each time it renders.

useRef

const refContainer = useRef(initialValue);
Copy the code
  • 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.

  • UseRef () is more useful than the ref attribute. It makes it easy to store any mutable value, similar to the way instance fields are used in class.

  • UseRef () creates a normal Javascript object. And create a {current:… The only difference with the} object is that useRef returns the same ref object every time it renders.

  • UseRef does not notify you when the ref object’s contents change. Changing the.current property does not cause component rerendering.

  • If you want to run some code when React binds or unbinds the REF of the DOM node, you need to use the ref callback to do so.

useImperativeHandle

useImperativeHandle(ref, createHandle, [deps])
Copy the code
  • UseImperativeHandle allows you to customize the instance value exposed to the parent component when using a ref.

  • In most cases, imperative code like ref should be avoided. UseImperativeHandle should be used together with the forwardRef

useLayoutEffect

  • Its function signature is the same as useEffect, but it calls Effect synchronously after all DOM changes.
    • You can use it to read DOM layouts and trigger rerenders synchronously.
  • The update schedule inside useLayoutEffect is refreshed synchronously before the browser performs the drawing.
  • Use standard Useeffects whenever possible to avoid blocking visual updates.
  • UseLayoutEffect and componentDidMount, componentDidUpdate call phase is the same.
    • It is recommended that you start with useEffect and only try use elayouteffect when something goes wrong.
  • Neither useLayoutEffect nor useEffect can be executed until the Javascript code is loaded.
    • This is why the React alarm is triggered when useLayoutEffect code is introduced into the server rendering component.
    • Solution 1: You need to move the code logic to useEffect (if it is not needed for the first rendering),
    • Solution 2: Delay the display of this component until the client rendering is complete (if the HTML is displayed incorrectly until useLayoutEffect is executed).
    • To exclude components that depend on layout effect from HTML rendered on the server, conditional rendering can be done using showChild && and useEffect(() => {setShowChild(true); }, []) delay the presentation of components. This way, the UI will not appear as cluttered as before until the client rendering is complete.

useDebugValue

useDebugValue(value)
Copy the code
  • UseDebugValue can be used to display tags for custom hooks in the React developer tool.
  • Formatting the display of values can be an expensive operation. Unless special cases of Hook need to be checked
    • Accepts a formatting function as an optional second argument.
    • This function is called only when the Hook is checked. It takes a debug value as an argument and returns a formatted display value.
  • It is not recommended to add debug values to every custom Hook. It is most valuable when it is part of a shared library.

Official Hooks FAQ

The official recommendation is to use Hooks as the main way to write the React component.

Hooks are friendly to static typing support.

The Hooks rule enforces two rules :(ESLint plugin) – calls to Hooks are made either inside a big hump named function (as a component) or inside another useSomething function (as a custom Hook). – Hook is called in the same order every time it is rendered.

Class’s lifecycle methods correspond to hook-constructor: function components do not need constructors. You can initialize state by calling useState. If the calculation is expensive, you can pass a function to useState. -getderivedStateFromprops: Changed to scheduling an update at render time. Shouldcomponentupdate-render: This is the function component body itself. – componentDidMount, componentDidUpdate, componentWillUnmount: useEffect Hook can express all of these combinations (including less common scenarios). – getSnapshotBeforeUpdate, componentDidCatch, and getDerivedStateFromError: There are no Hook equivalents for these methods, but they will be added soon.

Similar instance variables: useRef() Hook can be used for more than DOM refs. The “ref” object is a generic container with a mutable current attribute that can hold any value, similar to an instance attribute of a class.

When defining state variables, it is recommended to split state into multiple state variables, each containing different values that change at the same time.

Get props or state of the previous round manually by using ref.

If you see stale props and state in a function. – To read the latest state from some asynchronous callback, you can use a ref to save it, modify it, and read from it. – The dependency array optimization was used but all dependencies were not specified correctly.

Use the useReducer to force a rerender even if state does not change with an increased counter

The basic way to get the position or size of a DOM node is to use a callback ref. React calls the callback whenever a ref is attached to another node.

Conditional effects can be skipped during updates, and forgetting to process updates often leads to bugs, which is why we don’t use conditional effects by default.

Avoid declaring functions outside of effect. It is difficult to remember which functions and states are used by functions outside effect. – If there is no value in the component scope, it is safe to specify the conditional parameter as []

On special requirements, a ref can be used to hold a mutable variable, similar to this in class.

Implement shouldComponentUpdate by covering a component with react. memo to shallow compare its props

Using the useMemo Hook allows you to cache calculations between multiple renders by “remembering” the last one.

Aren’t hooks slowed down by creating functions at render time? In modern browsers, the raw performance of closures and classes differs significantly only in extreme scenarios.

The Hook design is more efficient in some ways: – Hooks avoid the extra overhead required by classes, such as the cost of creating class instances and binding event handlers in constructors. – Language-compliant code does not require deep tree nesting when using hooks. This is common in code bases that use higher-order components, render props, and context. The smaller the component tree, the smaller the React workload.

ShouldComponentUpdate optimizes how the React inline function that passes a new callback each time it renders will break subcomponents. Hook solves this problem in three ways. – useCallback Hook allows you to keep the same callback reference between rerenders so shouldComponentUpdate continues to work – useMemo Hook makes it easier to control when specific child nodes are updated, reducing the need for pure components.

- useReducer Hook reduces the dependence on deep-pass callbacks, as explained below.Copy the code

If a value is constantly changing, it is recommended to pass dispatches down in the context rather than using separate callbacks in the props.

A Hook is only called in the React component (or a custom Hook — again, only called in the React component).

The reason multiple useState() calls get their own independent local state. – Inside each component is a list of “memory cells”. They’re just JavaScript objects that we use to store some data. – When you call a Hook with useState(), it reads the current cell (or initializes it on first render) and moves the pointer to the next one.